Merge release branch 21.x into 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..554440c
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1 @@
+build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14
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/workflows/codespell.yml b/.github/workflows/codespell.yml
index 41dc715..2e5ee80 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,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,streem,sur"
+          ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,streem,sur,falsy"
diff --git a/.github/workflows/generated_cmake.yml b/.github/workflows/generated_cmake.yml
new file mode 100644
index 0000000..91dcd4f
--- /dev/null
+++ b/.github/workflows/generated_cmake.yml
@@ -0,0 +1,24 @@
+name: Generated CMake File Lists
+
+on:
+  - push
+  - pull_request
+
+jobs:
+  cmake:
+    runs-on: ubuntu-latest
+
+    strategy:
+      fail-fast: false   # Don't cancel all jobs if one fails.
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: Set up Bazel read-only caching
+        run: echo "BAZEL_CACHE_AUTH=--remote_upload_local_results=false" >> $GITHUB_ENV
+      - name: Generate CMake files
+        run: cd ${{ github.workspace }} && bazel build //pkg:gen_src_file_lists --test_output=errors $BAZEL_CACHE $BAZEL_CACHE_AUTH
+      - name: Compare to Golden file
+        run: diff -du bazel-bin/pkg/src_file_lists.cmake src/file_lists.cmake
+      - name: Report
+        run: echo "::error file=cmake/update_file_lists.sh::CMake files are stale, please run cmake/update_file_lists.sh"
+        if: failure()
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..e05b57b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,7 +1,8 @@
-[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
diff --git a/BUILD.bazel b/BUILD.bazel
index 0f6e41e..67cd2db 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,200 @@
 #
 # 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"],
 )
 
 ################################################################################
@@ -797,265 +255,40 @@
 # 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(
@@ -1079,6 +312,10 @@
     visibility = ["//visibility:public"],
 )
 
+################################################################################
+# Objective-C support
+################################################################################
+
 alias(
     name = "objectivec",
     actual = "//objectivec",
@@ -1094,84 +331,74 @@
 )
 
 ################################################################################
-# Test generated proto support
+# Test protos
 ################################################################################
 
+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 +406,7 @@
         "//conformance:__pkg__",
         "//java:__subpackages__",
     ],
-    deps = [":test_messages_proto2_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto2_proto"],
 )
 
 java_proto_library(
@@ -1188,7 +415,7 @@
         "//conformance:__pkg__",
         "//java:__subpackages__",
     ],
-    deps = [":test_messages_proto3_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto3_proto"],
 )
 
 java_lite_proto_library(
@@ -1197,7 +424,7 @@
         "//conformance:__pkg__",
         "//java:__subpackages__",
     ],
-    deps = [":test_messages_proto2_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto2_proto"],
 )
 
 java_lite_proto_library(
@@ -1206,7 +433,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 +524,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 +537,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 +545,20 @@
         "CMakeLists.txt",
         "CONTRIBUTORS.txt",
         "LICENSE",
-        "Makefile.am",
         "README.md",
         "WORKSPACE",
-        "autogen.sh",
-        "build_files_updated_unittest.sh",
         "cmake/CMakeLists.txt",
         "cmake/README.md",
+        "cmake/update_file_lists.sh",
         "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 +576,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 4be9411..2dc8633 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,48 @@
+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
+
+
+  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.
+
+  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.
+
+  Compiler
+  * Print full path name of source .proto file on error
+
 2022-09-13 version 21.6 (C++/Java/Python/PHP/Objective-C/C#/Ruby)
 
 C++
@@ -12,7 +57,6 @@
   Python
   * Fixed comparison of maps in Python.
 
-
 2022-07-25 version 21.4 (C++/Java/Python/PHP/Objective-C/C#/Ruby)
 
   C++
@@ -149,6 +193,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)
@@ -160,6 +205,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..76e2c4e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,11 +32,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 +69,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 +91,23 @@
 # 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)
+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 +172,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,7 +212,7 @@
 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() {
@@ -242,12 +260,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 +280,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 +315,54 @@
   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/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/Makefile.am b/Makefile.am
deleted file mode 100644
index 4c7c711..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,1291 +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/map.c                                       \
-  php/ext/google/protobuf/map.h                                       \
-  php/ext/google/protobuf/message.c                                   \
-  php/ext/google/protobuf/message.h                                   \
-  php/ext/google/protobuf/names.c                                     \
-  php/ext/google/protobuf/names.h                                     \
-  php/ext/google/protobuf/package.xml                                 \
-  php/ext/google/protobuf/php-upb.c                                   \
-  php/ext/google/protobuf/php-upb.h                                   \
-  php/ext/google/protobuf/php_protobuf.h                              \
-  php/ext/google/protobuf/protobuf.c                                  \
-  php/ext/google/protobuf/protobuf.h                                  \
-  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/README.md b/README.md
index c2e6575..3377f3a 100644
--- a/README.md
+++ b/README.md
@@ -42,8 +42,7 @@
 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,6 +62,7 @@
 | 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
 -----------
@@ -82,3 +82,10 @@
 web at:
 
 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..13c2bb0 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -9,32 +9,25 @@
 
 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",
     ],
 )
 
+# Bazel platform rules.
 http_archive(
-    name = "com_github_google_benchmark",
-    sha256 = "2a778d821997df7d8646c9c59b8edb9a573a6e04c534c01892a40aa524a7b68c",
-    strip_prefix = "benchmark-bf585a2789e30585b4e3ce6baf11ef2750b54677",
-    urls = [
-        "https://github.com/google/benchmark/archive/bf585a2789e30585b4e3ce6baf11ef2750b54677.zip",
-    ],
+    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 +62,11 @@
 
 load("@upb//bazel:workspace_deps.bzl", "upb_deps")
 upb_deps()
+
+load("@upb//bazel:system_python.bzl", "system_python")
+system_python(name = "local_config_python")
+
+bind(
+    name = "python_headers",
+    actual = "@local_config_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..4b99a01 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)
@@ -137,8 +141,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 +181,7 @@
      -Dprotobuf_BUILD_TESTS=OFF ^
      C:\Path\to\src\protobuf
 
-Compiling
-=========
+## Compiling
 
 The standard way to compile a *CMake* project is `cmake --build <directory>`.
 
@@ -206,8 +208,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 +260,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:
 
@@ -292,8 +292,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 +317,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 +367,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 +394,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..c1c4c16
--- /dev/null
+++ b/cmake/abseil-cpp.cmake
@@ -0,0 +1,58 @@
+# 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()")
+
+set(protobuf_ABSL_USED_TARGETS
+  absl::algorithm
+  absl::base
+  absl::bind_front
+  absl::bits
+  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::optional
+  absl::span
+  absl::status
+  absl::statusor
+  absl::strings
+  absl::synchronization
+  absl::time
+  absl::utility
+  absl::variant
+)
diff --git a/cmake/conformance.cmake b/cmake/conformance.cmake
index d6c435a..fa5c479 100644
--- a/cmake/conformance.cmake
+++ b/cmake/conformance.cmake
@@ -24,6 +24,9 @@
   ${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/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}/conformance/third_party/jsoncpp/json.h
   ${protobuf_SOURCE_DIR}/conformance/third_party/jsoncpp/jsoncpp.cpp
   ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
@@ -39,11 +42,24 @@
 
 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_CURRENT_BINARY_DIR}/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)
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..0dc8457 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,6 @@
 endif()
 set_target_properties(libprotobuf-lite PROPERTIES
     VERSION ${protobuf_VERSION}
-    SOVERSION 32
     OUTPUT_NAME ${LIB_PREFIX}protobuf-lite
     DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
 add_library(protobuf::libprotobuf-lite ALIAS libprotobuf-lite)
diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake
index 07e4bcf..19d6030 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,6 @@
 endif()
 set_target_properties(libprotobuf PROPERTIES
     VERSION ${protobuf_VERSION}
-    SOVERSION 32
     OUTPUT_NAME ${LIB_PREFIX}protobuf
     DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
 add_library(protobuf::libprotobuf ALIAS libprotobuf)
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index 15a47e5..3be0df3 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,6 @@
 set_target_properties(libprotoc PROPERTIES
     COMPILE_DEFINITIONS LIBPROTOC_EXPORTS
     VERSION ${protobuf_VERSION}
-    SOVERSION 32
     OUTPUT_NAME ${LIB_PREFIX}protoc
     DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
 add_library(protobuf::libprotoc ALIAS libprotoc)
diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
index 6166911..1a8d243 100644
--- a/cmake/protobuf-config.cmake.in
+++ b/cmake/protobuf-config.cmake.in
@@ -3,165 +3,13 @@
 
 # Depend packages
 @_protobuf_FIND_ZLIB@
+@_protobuf_FIND_ABSL@
 
 # 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..a9fdd52 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,59 +40,16 @@
   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_proto_srcs}
 )
 
 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_proto_srcs}
+  ${compiler_test_protos_files}
+  ${util_test_protos_files}
 )
 
 macro(compile_proto_file filename)
@@ -118,110 +76,32 @@
   set(tests_proto_files ${tests_proto_files} ${pb_file})
 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)
+  ${lite_test_util_srcs} ${lite_test_proto_files})
+target_include_directories(protobuf-lite-test-common PRIVATE ${ABSL_ROOT_DIR})
+target_link_libraries(protobuf-lite-test-common
+  ${protobuf_LIB_PROTOBUF_LITE} ${protobuf_ABSL_USED_TARGETS} 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}
+  ${test_util_srcs}
+  ${mock_code_generator_srcs}
+  ${testing_srcs}
 )
 
 add_library(protobuf-test-common STATIC
   ${common_test_files} ${tests_proto_files})
-target_link_libraries(protobuf-test-common libprotobuf GTest::gmock)
+target_include_directories(protobuf-test-common PRIVATE ${ABSL_ROOT_DIR})
+target_link_libraries(protobuf-test-common
+  ${protobuf_LIB_PROTOBUF} ${protobuf_ABSL_USED_TARGETS} 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)
@@ -254,41 +134,65 @@
     /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-lite-test-common protobuf-test-common ${protobuf_LIB_PROTOC} ${protobuf_LIB_PROTOBUF} 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}
+  ${mock_code_generator_srcs}
+  ${testing_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})
+target_link_libraries(lite-test protobuf-lite-test-common ${protobuf_LIB_PROTOBUF_LITE} 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)
+
+# Explicitly skip the bootstrapping headers as it's directly used in tests
+set(_installed_hdrs ${libprotobuf_hdrs} ${libprotoc_hdrs})
+list(REMOVE_ITEM _installed_hdrs
+  "${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.pb.h"
+  "${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.pb.h")
+
+foreach(_hdr ${_installed_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)
+  add_dependencies(protobuf-lite-test-common remove-installed-headers)
+  add_dependencies(protobuf-test-common remove-installed-headers)
+endif()
diff --git a/cmake/update_file_lists.sh b/cmake/update_file_lists.sh
new file mode 100755
index 0000000..a08bdf3
--- /dev/null
+++ b/cmake/update_file_lists.sh
@@ -0,0 +1,8 @@
+#!/bin/bash -u
+
+# This script generates file lists from Bazel for CMake.
+
+set -e
+
+bazel build //pkg:gen_src_file_lists
+cp -v bazel-bin/pkg/src_file_lists.cmake src/file_lists.cmake
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index c42fbc2..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.6],[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..0c37e15 100644
--- a/conformance/BUILD.bazel
+++ b/conformance/BUILD.bazel
@@ -1,6 +1,8 @@
 # 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",
@@ -10,21 +12,38 @@
 )
 
 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 +53,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,6 +81,51 @@
     deps = [":conformance_proto"],
 )
 
+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(
     name = "jsoncpp",
     srcs = ["third_party/jsoncpp/jsoncpp.cpp"],
@@ -71,7 +143,7 @@
         "conformance_test.h",
     ],
     includes = ["."],
-    deps = [":conformance_proto_cc"],
+    deps = [":conformance_cc_proto"],
 )
 
 cc_library(
@@ -83,6 +155,7 @@
         ":jsoncpp",
         ":test_messages_proto2_proto_cc",
         ":test_messages_proto3_proto_cc",
+        "@com_google_absl//absl/status",
     ],
 )
 
@@ -108,8 +181,24 @@
     ],
 )
 
+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 +215,7 @@
 
 java_binary(
     name = "conformance_java_lite",
+    testonly = 1,
     srcs = ["ConformanceJavaLite.java"],
     main_class = "ConformanceJavaLite",
     visibility = [
@@ -140,10 +230,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 +351,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",
         ],
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..7accca3 100644
--- a/conformance/binary_json_conformance_suite.cc
+++ b/conformance/binary_json_conformance_suite.cc
@@ -30,15 +30,15 @@
 
 #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 "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 "absl/status/status.h"
 #include "third_party/jsoncpp/json.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"
 
 namespace proto2_messages = protobuf_test_messages::proto2;
 
@@ -354,7 +354,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 +384,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 +403,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 +440,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);
 
@@ -571,7 +571,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");
 
@@ -615,7 +615,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 +642,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 +765,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 +788,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 +850,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 +866,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 +900,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 +978,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 +992,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 +1006,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 +1020,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 +1038,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 +1052,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 +1067,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 +1108,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 +1134,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 +1150,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 +1190,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 +1240,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",
@@ -2724,6 +2741,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/conformance.proto b/conformance/conformance.proto
index 7248e98..a9edbab 100644
--- a/conformance/conformance.proto
+++ b/conformance/conformance.proto
@@ -92,10 +92,6 @@
   // 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;
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_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..cffadc9 100755
--- a/conformance/conformance_python.py
+++ b/conformance/conformance_python.py
@@ -42,7 +42,7 @@
 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
+from conformance import conformance_pb2
 
 sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
 sys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0)
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc
index 2c856f5..03b8a4c 100644
--- a/conformance/conformance_test.cc
+++ b/conformance/conformance_test.cc
@@ -36,13 +36,13 @@
 #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/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/conformance.pb.h"
 
 using conformance::ConformanceRequest;
 using conformance::ConformanceResponse;
@@ -129,7 +129,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_));
 }
@@ -290,7 +290,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);
diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h
index 2861598..5adf3f9 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/wire_format_lite.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "conformance/conformance.pb.h"
 
 namespace conformance {
 class ConformanceRequest;
@@ -124,7 +124,7 @@
 //    class MyConformanceTestSuite : public ConformanceTestSuite {
 //     public:
 //      void RunSuiteImpl() {
-//        // INSERT ACTURAL TESTS.
+//        // INSERT ACTUAL TESTS.
 //      }
 //    };
 //
diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc
index 2aac35c..47e91a7 100644
--- a/conformance/conformance_test_runner.cc
+++ b/conformance/conformance_test_runner.cc
@@ -62,8 +62,8 @@
 #include <fstream>
 #include <vector>
 
-#include <google/protobuf/stubs/stringprintf.h>
-#include "conformance.pb.h"
+#include "google/protobuf/stubs/stringprintf.h"
+#include "conformance/conformance.pb.h"
 #include "conformance_test.h"
 
 using conformance::ConformanceResponse;
@@ -73,10 +73,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 +93,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 +105,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 +120,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,18 +136,16 @@
           "                              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();
   }
@@ -170,11 +165,9 @@
 
     string error_msg;
     if (WIFEXITED(status)) {
-      StringAppendF(&error_msg,
-                    "child exited, status=%d", WEXITSTATUS(status));
+      StringAppendF(&error_msg, "child exited, status=%d", WEXITSTATUS(status));
     } else if (WIFSIGNALED(status)) {
-      StringAppendF(&error_msg,
-                    "child killed by signal %d", WTERMSIG(status));
+      StringAppendF(&error_msg, "child killed by signal %d", WTERMSIG(status));
     }
     GOOGLE_LOG(INFO) << error_msg;
     child_pid_ = -1;
@@ -186,17 +179,17 @@
   }
 
   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;
@@ -216,7 +209,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 +220,7 @@
           UsageError();
         }
       } else {
-        program += argv[arg];
+        program += argv[arg++];
         while (arg < argc) {
           program_args.push_back(argv[arg]);
           arg++;
@@ -238,8 +231,8 @@
     ForkPipeRunner runner(program, program_args);
 
     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 +296,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,7 +317,7 @@
 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);
+    ssize_t bytes_read = read(fd, (char *)buf + ofs, len);
 
     if (bytes_read == 0) {
       GOOGLE_LOG(ERROR) << current_test_name_ << ": unexpected EOF from test program";
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..a68602c 100644
--- a/conformance/failure_list_cpp.txt
+++ b/conformance/failure_list_cpp.txt
@@ -12,8 +12,6 @@
 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
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..3232047a 100644
--- a/conformance/failure_list_php.txt
+++ b/conformance/failure_list_php.txt
@@ -8,6 +8,8 @@
 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..52ca454 100644
--- a/conformance/failure_list_php_c.txt
+++ b/conformance/failure_list_php_c.txt
@@ -1,2 +1,5 @@
 Recommended.Proto2.JsonInput.FieldNameExtension.Validator
 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
+Required.Proto3.JsonInput.DurationNegativeNanos.JsonOutput
+Required.Proto3.JsonInput.DurationNegativeNanos.ProtobufOutput
+Required.Proto3.JsonInput.DurationNegativeSeconds.JsonOutput
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index 4938202..ff230a2 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -56,3 +56,6 @@
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Required.Proto3.JsonInput.DurationNegativeNanos.JsonOutput
+Required.Proto3.JsonInput.DurationNegativeNanos.ProtobufOutput
+Required.Proto3.JsonInput.DurationNegativeSeconds.JsonOutput
diff --git a/conformance/text_format_conformance_suite.cc b/conformance/text_format_conformance_suite.cc
index 460bc24..999f333 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;
 
@@ -85,7 +85,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());
@@ -104,7 +104,7 @@
     case ConformanceResponse::kTextPayload: {
       if (requested_output != conformance::TEXT_FORMAT) {
         ReportFailure(test_name, level, request, response,
-                      StrCat("Test was asked for ",
+                      absl::StrCat("Test was asked for ",
                                    WireFormatToString(requested_output),
                                    " output but provided TEXT_FORMAT instead.")
                           .c_str());
@@ -141,7 +141,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);
@@ -263,64 +263,64 @@
     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'"));
+        absl::StrCat("StringLiteralConcat", field_type), REQUIRED,
+        absl::StrCat(field_name, ": 'first' \"second\"\n'third'"));
     RunValidTextFormatTest(
-        StrCat("StringLiteralBasicEscapes", field_type), REQUIRED,
-        StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'"));
+        absl::StrCat("StringLiteralBasicEscapes", field_type), REQUIRED,
+        absl::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),
+        absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED,
+        absl::StrCat(field_name, ": '\\341\\210\\264'"));
+    RunValidTextFormatTest(absl::StrCat("StringLiteralHexEscapes", field_type),
                            REQUIRED,
-                           StrCat(field_name, ": '\\xe1\\x88\\xb4'"));
+                           absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'"));
     RunValidTextFormatTest(
-        StrCat("StringLiteralShortUnicodeEscape", field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\u1234'"));
+        absl::StrCat("StringLiteralShortUnicodeEscape", field_type),
+        RECOMMENDED, absl::StrCat(field_name, ": '\\u1234'"));
     RunValidTextFormatTest(
-        StrCat("StringLiteralLongUnicodeEscapes", field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\U00001234\\U00010437'"));
+        absl::StrCat("StringLiteralLongUnicodeEscapes", field_type),
+        RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'"));
     // String literals don't include line feeds.
-    ExpectParseFailure(StrCat("StringLiteralIncludesLF", field_type),
+    ExpectParseFailure(absl::StrCat("StringLiteralIncludesLF", field_type),
                        REQUIRED,
-                       StrCat(field_name, ": 'first line\nsecond line'"));
+                       absl::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'"));
+        absl::StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type),
+        REQUIRED, absl::StrCat(field_name, ": '\\U00110000'"));
     // Unicode escapes don't include surrogates.
     ExpectParseFailure(
-        StrCat("StringLiteralShortUnicodeEscapeSurrogatePair",
+        absl::StrCat("StringLiteralShortUnicodeEscapeSurrogatePair",
                      field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\ud801\\udc37'"));
+        RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\udc37'"));
     ExpectParseFailure(
-        StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly",
+        absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly",
                      field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\ud800'"));
+        RECOMMENDED, absl::StrCat(field_name, ": '\\ud800'"));
     ExpectParseFailure(
-        StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly",
+        absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly",
                      field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\udc00'"));
+        RECOMMENDED, absl::StrCat(field_name, ": '\\udc00'"));
     ExpectParseFailure(
-        StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly",
+        absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly",
                      field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\U0000d800'"));
+        RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d800'"));
     ExpectParseFailure(
-        StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly",
+        absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly",
                      field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\U0000dc00'"));
+        RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'"));
     ExpectParseFailure(
-        StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\U0000d801\\U00000dc37'"));
+        absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type),
+        RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'"));
     ExpectParseFailure(
-        StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort",
+        absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort",
                      field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\U0000d801\\udc37'"));
+        RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\udc37'"));
     ExpectParseFailure(
-        StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong",
+        absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong",
                      field_type),
-        RECOMMENDED, StrCat(field_name, ": '\\ud801\\U0000dc37'"));
+        RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\U0000dc37'"));
 
     // The following method depend on the type of field, as strings have extra
     // validation.
@@ -330,10 +330,10 @@
             : &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'"));
+    (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
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..62c9638 100644
--- a/csharp/.gitignore
+++ b/csharp/.gitignore
@@ -18,6 +18,7 @@
 # 	Untracked files
 #
 .vs
+.cr
 *.user
 *.suo
 *.nupkg
diff --git a/csharp/BUILD.bazel b/csharp/BUILD.bazel
index 2c15084..9f9e83a 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.cs",
+        "src/Google.Protobuf/WellKnownTypes/Any.cs",
+        "src/Google.Protobuf/WellKnownTypes/Api.cs",
+        "src/Google.Protobuf/WellKnownTypes/Duration.cs",
+        "src/Google.Protobuf/WellKnownTypes/Empty.cs",
+        "src/Google.Protobuf/WellKnownTypes/FieldMask.cs",
+        "src/Google.Protobuf/WellKnownTypes/SourceContext.cs",
+        "src/Google.Protobuf/WellKnownTypes/Struct.cs",
+        "src/Google.Protobuf/WellKnownTypes/Timestamp.cs",
+        "src/Google.Protobuf/WellKnownTypes/Type.cs",
+        "src/Google.Protobuf/WellKnownTypes/Wrappers.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/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..f9fff22
--- /dev/null
+++ b/csharp/build_release.sh
@@ -0,0 +1,14 @@
+#!/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
+
+# Work around https://github.com/dotnet/core/issues/5881
+dotnet nuget locals all --clear
+
+# Builds Google.Protobuf NuGet packages
+dotnet restore src/Google.Protobuf.sln
+dotnet pack -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/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..cfd6082 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
@@ -40,7 +42,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
@@ -73,17 +76,3 @@
 # AddressBook sample protos
 $PROTOC -Iexamples -Isrc --csharp_out=csharp/src/AddressBook \
     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_issues.proto b/csharp/protos/unittest_issues.proto
index f46c20e..d5907bb 100644
--- a/csharp/protos/unittest_issues.proto
+++ b/csharp/protos/unittest_issues.proto
@@ -59,10 +59,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 +171,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/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/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.cs
index 57e59a9..d3284a4 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.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.cs
index 35f2b8a..d573455 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
@@ -213,12 +213,13 @@
             "dGlvbmFsX2Jvb2wY7gcgASgIEhcKDnJlcGVhdGVkX2ludDMyGPMHIAMoBRoa",
             "Cg1PcHRpb25hbEdyb3VwEgkKAWEYASABKAUiFgoUTnVsbEh5cG90aGVzaXNQ",
             "cm90bzIiLwoORW51bU9ubHlQcm90bzIiHQoEQm9vbBIKCgZrRmFsc2UQABIJ",
-            "CgVrVHJ1ZRABIh8KD09uZVN0cmluZ1Byb3RvMhIMCgRkYXRhGAEgASgJKkYK",
-            "EUZvcmVpZ25FbnVtUHJvdG8yEg8KC0ZPUkVJR05fRk9PEAASDwoLRk9SRUlH",
-            "Tl9CQVIQARIPCgtGT1JFSUdOX0JBWhACOkoKD2V4dGVuc2lvbl9pbnQzMhIx",
-            "LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8yLlRlc3RBbGxUeXBlc1By",
-            "b3RvMhh4IAEoBUIvCihjb20uZ29vZ2xlLnByb3RvYnVmX3Rlc3RfbWVzc2Fn",
-            "ZXMucHJvdG8ySAH4AQE="));
+            "CgVrVHJ1ZRABIh8KD09uZVN0cmluZ1Byb3RvMhIMCgRkYXRhGAEgASgJIkYK",
+            "EVByb3RvV2l0aEtleXdvcmRzEg4KBmlubGluZRgBIAEoBRIPCgdjb25jZXB0",
+            "GAIgASgJEhAKCHJlcXVpcmVzGAMgAygJKkYKEUZvcmVpZ25FbnVtUHJvdG8y",
+            "Eg8KC0ZPUkVJR05fRk9PEAASDwoLRk9SRUlHTl9CQVIQARIPCgtGT1JFSUdO",
+            "X0JBWhACOkoKD2V4dGVuc2lvbl9pbnQzMhIxLnByb3RvYnVmX3Rlc3RfbWVz",
+            "c2FnZXMucHJvdG8yLlRlc3RBbGxUeXBlc1Byb3RvMhh4IAEoBUIvCihjb20u",
+            "Z29vZ2xlLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8ySAH4AQE="));
       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 +232,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 +4344,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 +8302,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.cs
index 520216f..74e2a57 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.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.cs
index c1f43ce..7f1aca1 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.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/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs
index 3fe2dd6..3278517 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.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/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
index 3ec8d35..50b9046 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.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..b5d6c0b 100644
--- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
@@ -641,7 +641,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 +758,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 +1066,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%
copy from csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs
copy 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..f3651df 100644
--- a/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs
+++ b/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs
@@ -77,43 +77,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%
rename from csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs
rename 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..ae89679 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..b0bebec 100644
--- a/csharp/src/Google.Protobuf.sln
+++ b/csharp/src/Google.Protobuf.sln
@@ -12,8 +12,6 @@
 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

@@ -42,10 +40,6 @@
 		{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

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.cs b/csharp/src/Google.Protobuf/Compiler/Plugin.cs
new file mode 100644
index 0000000..f3a6c17
--- /dev/null
+++ b/csharp/src/Google.Protobuf/Compiler/Plugin.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 33db8a8..af93a2c 100644
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -5,8 +5,7 @@
     <Copyright>Copyright 2015, Google Inc.</Copyright>
     <AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
     <VersionPrefix>3.21.6</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..3575e25 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");
             }
         }
 
@@ -853,7 +846,7 @@
                 if (secondsToAdd < 0 && nanosToAdd > 0)
                 {
                     secondsToAdd++;
-                    nanosToAdd = nanosToAdd - Duration.NanosecondsPerSecond;
+                    nanosToAdd -= Duration.NanosecondsPerSecond;
                 }
                 if (secondsToAdd != 0 || nanosToAdd != 0)
                 {
@@ -1049,23 +1042,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.cs
index 1cb43c0..e252372 100644
--- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.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/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/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/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/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
index 8c1eec5..aa25686 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.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/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/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/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/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..dc19688 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -320,3 +320,27 @@
 1. Protoc-gen-authz
    * Website: https://github.com/Neakxs/protoc-gen-authz
    * Extension: 1145
+
+1. Protonium
+   * Website: https://github.com/zyp/protonium
+   * Extension: 1146
+
+1. Protoc-gen-xo
+   * Website: https://github.com/xo/ecosystem
+   * Extension: 1147
+
+1. Ballerina gRPC
+   * Website: https://github.com/ballerina-platform/module-ballerina-grpc
+   * Extension: 1148
+
+1. Protoc-gen-referential-integrity
+   * Website: https://github.com/ComponentCorp/protoc-gen-referential-integrity
+   * Extension: 1149
+
+1. Oclea Service Layer RPC
+   * Website: https://oclea.com/
+   * Extension: 1150
+
+1. mypy-protobuf
+   * Website: https://github.com/nipunn1313/mypy-protobuf
+   * Extension: 1151-1154
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/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..430568e 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -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_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..5a5eed9 100644
--- a/java/core/BUILD.bazel
+++ b/java/core/BUILD.bazel
@@ -191,7 +191,7 @@
     maven_coordinates = "com.google.protobuf:protobuf-java:%s" % PROTOBUF_JAVA_VERSION,
     pom_template = "pom_template.xml",
     resources = [
-        "//:built_in_runtime_protos",
+        "//src/google/protobuf:descriptor_proto_srcs",
         "//:well_known_type_protos",
     ],
     tags = ["manual"],
@@ -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",
     ],
@@ -440,12 +461,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/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..0e03ebd 100644
--- a/java/core/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -385,8 +385,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.
@@ -1130,13 +1129,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 +1143,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 +1151,7 @@
         byteString.writeTo(out);
       }
 
-      out.write(copyArray(cachedBuffer, cachedBufferPos));
+      out.write(Arrays.copyOf(cachedBuffer, cachedBufferPos));
     }
 
     /**
@@ -1210,7 +1202,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.
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/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java
index a36195b..91c9b19 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);
     }
 
     /**
@@ -1788,6 +1788,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/ExtensionRegistryLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
index caa58e1..4b2aa07 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -123,16 +123,15 @@
    * 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();
         }
       }
     }
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 9db3345..0c16000 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -137,7 +137,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();
     }
@@ -244,11 +244,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);
   }
 
@@ -1245,11 +1250,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;
@@ -1261,7 +1266,7 @@
       }
     }
 
-    Object singularFromFieldSetType(final Object value) {
+    Object singularFromFieldSetType(Object value) {
       if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
         return descriptor.enumTypeMap.findValueByNumber((Integer) value);
       } else {
@@ -1269,12 +1274,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;
@@ -1286,7 +1290,7 @@
       }
     }
 
-    Object singularToFieldSetType(final Object value) {
+    Object singularToFieldSetType(Object value) {
       if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
         return ((Internal.EnumLite) value).getNumber();
       } else {
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 f1e5ac7..2b8f807 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,7 @@
    */
   protected static boolean alwaysUseFieldBuilders = false;
 
-  /** For use by generated code only.  */
+  /** For use by generated code only. */
   protected UnknownFieldSet unknownFields;
 
   protected GeneratedMessageV3() {
@@ -100,31 +98,29 @@
 
   @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)
-  */
+  /**
+   * @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}.
    */
   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();
 
@@ -149,16 +145,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<FieldDescriptor, Object>();
     final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
     final List<FieldDescriptor> fields = descriptor.getFields();
 
@@ -214,8 +208,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;
@@ -234,23 +228,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
@@ -274,12 +264,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);
@@ -287,20 +276,17 @@
 
   @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.");
   }
 
   /**
@@ -342,8 +328,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) {
@@ -351,8 +337,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) {
@@ -360,8 +346,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) {
@@ -369,8 +356,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) {
@@ -378,8 +365,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) {
@@ -480,63 +467,53 @@
   }
 
 
-
   /**
    * 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.");
   }
 
-  /**
-   * 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 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.
    */
   protected interface BuilderParent extends AbstractMessage.BuilderParent {}
 
-  /**
-   * TODO(xiaofeng): remove this together with GeneratedMessageV3.BuilderParent.
-   */
+  /** TODO(xiaofeng): remove this together with GeneratedMessageV3.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;
@@ -547,8 +524,7 @@
     // to dispatch dirty invalidations. See GeneratedMessageV3.BuilderListener.
     private boolean isClean;
 
-    private UnknownFieldSet unknownFields =
-        UnknownFieldSet.getDefaultInstance();
+    private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance();
 
     protected Builder() {
       this(null);
@@ -563,9 +539,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();
@@ -573,8 +547,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() {
@@ -592,15 +566,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() {
@@ -610,9 +583,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();
 
@@ -628,8 +600,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();
 
@@ -681,8 +652,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
@@ -732,21 +702,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;
     }
 
@@ -768,20 +735,16 @@
     }
 
     /**
-     * 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) {
       return setUnknownFieldsInternal(unknownFields);
     }
 
     @Override
-    public BuilderType mergeUnknownFields(
-        final UnknownFieldSet unknownFields) {
+    public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
       return setUnknownFields(
-        UnknownFieldSet.newBuilder(this.unknownFields)
-                       .mergeFrom(unknownFields)
-                       .build());
+          UnknownFieldSet.newBuilder(this.unknownFields).mergeFrom(unknownFields).build());
     }
 
 
@@ -797,16 +760,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;
             }
           }
@@ -821,9 +783,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 {
 
@@ -835,6 +796,7 @@
 
     /**
      * Gets the {@link BuilderParent} for giving to our children.
+     *
      * @return The builder parent for our children.
      */
     protected BuilderParent getParentForChildren() {
@@ -845,8 +807,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) {
@@ -858,22 +820,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. */
@@ -881,36 +840,30 @@
     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(
@@ -941,16 +894,13 @@
   }
 
   /**
-   * 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:
    *
@@ -975,10 +925,8 @@
    *
    * <p>See also {@link ExtendableBuilder}.
    */
-  public abstract static class ExtendableMessage<
-        MessageType extends ExtendableMessage>
-      extends GeneratedMessageV3
-      implements ExtendableMessageOrBuilder<MessageType> {
+  public abstract static class ExtendableMessage<MessageType extends ExtendableMessage>
+      extends GeneratedMessageV3 implements ExtendableMessageOrBuilder<MessageType> {
 
     private static final long serialVersionUID = 1L;
 
@@ -988,22 +936,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()
+                + "\".");
       }
     }
 
@@ -1041,12 +987,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);
@@ -1062,8 +1006,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. */
@@ -1128,10 +1072,15 @@
         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);
     }
 
     /**
@@ -1143,31 +1092,28 @@
         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.
-     */
+    /** 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;
 
@@ -1178,19 +1124,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
@@ -1214,6 +1159,7 @@
     protected ExtensionWriter newExtensionWriter() {
       return new ExtensionWriter(false);
     }
+
     protected ExtensionWriter newMessageSetExtensionWriter() {
       return new ExtensionWriter(true);
     }
@@ -1222,6 +1168,7 @@
     protected int extensionsSerializedSize() {
       return extensions.getSerializedSize();
     }
+
     protected int extensionsSerializedSizeAsMessageSet() {
       return extensions.getMessageSetSerializedSize();
     }
@@ -1293,8 +1240,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);
@@ -1305,23 +1251,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:
    *
@@ -1350,17 +1292,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.Builder<FieldDescriptor> extensions;
 
     protected ExtendableBuilder() {}
 
-    protected ExtendableBuilder(
-        BuilderParent parent) {
+    protected ExtendableBuilder(BuilderParent parent) {
       super(parent);
     }
 
@@ -1381,16 +1321,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()
+                + "\".");
       }
     }
 
@@ -1425,12 +1364,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);
@@ -1454,8 +1391,7 @@
 
     /** 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);
@@ -1469,30 +1405,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;
     }
@@ -1603,8 +1536,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() {
       return extensions == null
@@ -1694,8 +1626,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) {
@@ -1744,8 +1675,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();
@@ -1771,8 +1701,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();
@@ -1785,8 +1715,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();
@@ -1817,8 +1746,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.");
       }
     }
   }
@@ -1826,8 +1754,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();
@@ -1844,8 +1772,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);
     }
   }
 
@@ -1857,8 +1785,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) {
@@ -1867,7 +1794,7 @@
         throw (Error) cause;
       } else {
         throw new RuntimeException(
-          "Unexpected exception thrown by generated accessor method.", cause);
+            "Unexpected exception thrown by generated accessor method.", cause);
       }
     }
   }
@@ -1885,25 +1812,24 @@
   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,
@@ -1915,12 +1841,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()];
@@ -1931,16 +1855,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);
@@ -1952,36 +1879,54 @@
           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, 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);
             }
           }
         }
@@ -2007,13 +1952,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()];
     }
@@ -2021,38 +1964,53 @@
     /** 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 getRaw(GeneratedMessageV3 message);
+
       Object getRaw(GeneratedMessageV3.Builder builder);
+
       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 setRepeated(Builder builder, int index, Object value);
+
       void addRepeated(Builder builder, Object value);
+
       boolean has(GeneratedMessageV3 message);
+
       boolean has(GeneratedMessageV3.Builder builder);
+
       int getRepeatedCount(GeneratedMessageV3 message);
+
       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 getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index);
     }
 
     /** OneofAccessor provides access to a single oneof. */
@@ -2280,48 +2238,59 @@
       public Object get(final GeneratedMessageV3 message) {
         return invoker.get(message);
       }
+
       @Override
       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) {
         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) {
         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) {
         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.");
       }
+
       @Override
       public boolean has(final GeneratedMessageV3 message) {
         if (!hasHasMethod) {
@@ -2332,6 +2301,7 @@
         }
         return invoker.has(message);
       }
+
       @Override
       public boolean has(GeneratedMessageV3.Builder builder) {
         if (!hasHasMethod) {
@@ -2342,29 +2312,35 @@
         }
         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) {
         throw new UnsupportedOperationException(
             "getRepeatedFieldSize() called on a singular field.");
       }
+
       @Override
       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) {
         throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
       }
+
       @Override
       public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
         throw new UnsupportedOperationException(
@@ -2435,8 +2411,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);
         }
 
@@ -2453,8 +2428,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);
         }
@@ -2480,7 +2454,8 @@
       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) {
         ReflectionInvoker reflectionInvoker =
@@ -2497,18 +2472,22 @@
       public Object get(final GeneratedMessageV3 message) {
         return invoker.get(message);
       }
+
       @Override
       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) {
         // Add all the elements individually.  This serves two purposes:
@@ -2520,59 +2499,73 @@
           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) {
         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) {
         invoker.setRepeated(builder, index, value);
       }
+
       @Override
       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) {
         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) {
         return invoker.getRepeatedCount(builder);
       }
+
       @Override
       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) {
         throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
       }
+
       @Override
       public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
         throw new UnsupportedOperationException(
@@ -2582,16 +2575,15 @@
 
     private static class MapFieldAccessor implements FieldAccessor {
       MapFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
           final Class<? extends Builder> builderClass) {
         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;
@@ -2605,10 +2597,8 @@
         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) {
@@ -2695,14 +2685,12 @@
 
       @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.");
+        throw new UnsupportedOperationException("hasField() is not supported for repeated fields.");
       }
 
       @Override
@@ -2727,8 +2715,7 @@
 
       @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
@@ -2739,10 +2726,10 @@
 
     // ---------------------------------------------------------------
 
-    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 String containingOneofCamelCaseName) {
@@ -2755,12 +2742,9 @@
 
         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);
         }
       }
 
@@ -2804,10 +2788,10 @@
       }
     }
 
-    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) {
         super(descriptor, camelCaseName, messageClass, builderClass);
@@ -2829,6 +2813,7 @@
               getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
         }
       }
+
       private EnumDescriptor enumDescriptor;
 
       private final Method valueOfMethod;
@@ -2894,6 +2879,7 @@
         }
         super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value));
       }
+
       @Override
       public void addRepeated(final Builder builder, final Object value) {
         if (supportUnknownEnumValue) {
@@ -2912,29 +2898,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 GeneratedMessageV3> 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;
@@ -2964,19 +2946,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 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;
@@ -3000,27 +2980,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(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) {
         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;
@@ -3044,27 +3026,30 @@
       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 GeneratedMessageV3.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 {
@@ -3116,8 +3101,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 {
@@ -3129,7 +3114,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);
@@ -3144,11 +3130,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());
     }
   }
 
@@ -3171,11 +3154,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());
     }
   }
 
@@ -3197,11 +3177,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());
     }
   }
 
@@ -3228,28 +3205,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..0fb934f 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -600,6 +600,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 +621,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 +642,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 +663,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,6 +684,7 @@
     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. */
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..f641739 100644
--- a/java/core/src/main/java/com/google/protobuf/Message.java
+++ b/java/core/src/main/java/com/google/protobuf/Message.java
@@ -39,11 +39,12 @@
  *
  * <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.)
@@ -102,6 +103,7 @@
     // (From MessageLite.Builder, re-declared here only for return type
     // covariance.)
     @Override
+    @CanIgnoreReturnValue
     Builder clear();
 
     /**
@@ -121,6 +123,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 +138,11 @@
     Builder clone();
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(CodedInputStream input) throws IOException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
         throws IOException;
 
@@ -190,18 +195,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 +220,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 +229,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 +246,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..d631469 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 {
 
   /**
@@ -138,6 +139,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 +183,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 +196,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 +213,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 +225,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 +238,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 +250,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 +262,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 +275,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 +293,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 +309,7 @@
      *
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
         throws IOException;
 
@@ -317,6 +329,7 @@
      *
      * <p>This is equivalent to the {@code Message::MergeFrom} method in C++.
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(MessageLite other);
 
     /**
@@ -326,9 +339,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 +351,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/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..ca25756 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)
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 78a4a21..c235495 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 7317f49..7fba30a 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -116,8 +116,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);
@@ -459,9 +459,7 @@
       }
     }
 
-    /**
-     * 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;
 
@@ -953,6 +951,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 +1377,6 @@
     private ParseException floatParseException(final NumberFormatException e) {
       return parseException("Couldn't parse number: " + e.getMessage());
     }
-
   }
 
   /** Thrown when parsing an invalid text format message. */
@@ -1551,7 +1549,7 @@
      * 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, String fieldName) {
     }
 
     /**
@@ -1628,8 +1626,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 +1635,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;
@@ -1725,7 +1722,8 @@
 
     static final class UnknownField {
       static enum Type {
-        FIELD, EXTENSION;
+        FIELD,
+        EXTENSION;
       }
 
       final String message;
@@ -1786,7 +1784,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()) {
@@ -1803,12 +1800,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,26 +1812,28 @@
         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 =
@@ -1866,7 +1860,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 +1884,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,7 +1904,7 @@
         // 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, name);
         if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("{") && !tokenizer.lookingAt("<")) {
           skipFieldValue(tokenizer);
         } else {
@@ -1920,7 +1915,7 @@
 
       // Handle potential ':'.
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        detectSilentMarker(tokenizer);
+        detectSilentMarker(tokenizer, field.getFullName());
         tokenizer.tryConsume(":"); // optional
         if (parseTreeBuilder != null) {
           TextFormatParseInfoTree.Builder childParseTreeBuilder =
@@ -1944,7 +1939,7 @@
               unknownFields);
         }
       } else {
-        detectSilentMarker(tokenizer);
+        detectSilentMarker(tokenizer, field.getFullName());
         tokenizer.consume(":"); // required
         consumeFieldValues(
             tokenizer,
@@ -1967,6 +1962,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 +2076,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 +2229,7 @@
           throw tokenizer.parseExceptionPreviousToken("Expected a valid type URL.");
         }
       }
-      detectSilentMarker(tokenizer);
+      detectSilentMarker(tokenizer, typeUrlBuilder.toString());
       tokenizer.tryConsume(":");
       final String anyEndToken;
       if (tokenizer.tryConsume("<")) {
@@ -2244,15 +2267,7 @@
 
     /** 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();
-      }
+      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,7 +2275,7 @@
       // 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, name);
       if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("<") && !tokenizer.lookingAt("{")) {
         skipFieldValue(tokenizer);
       } else {
@@ -2469,9 +2484,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/UnsafeByteOperations.java b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
index 16521e1..be6f97d 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>
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..7988e7c 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;
@@ -463,15 +464,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 +487,6 @@
     }
   }
 
-
   /**
    * Tests the translate/crosslink for an example where a message field's name and type name are the
    * same.
@@ -560,8 +560,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 +625,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 +660,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 +699,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 +798,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 +845,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/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 55864af..01c2f4b 100644
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -1529,7 +1529,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 +1943,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/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/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..ad512a9 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();
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/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
index cde1776..1a76848 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 {
 
@@ -825,6 +823,7 @@
     }
   }
 
+  @CanIgnoreReturnValue
   private TestAllTypes assertParseSuccessWithOverwriteForbidden(String text)
       throws TextFormat.ParseException {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -1450,6 +1449,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 +1773,7 @@
     }
   }
 
+  @SuppressWarnings("LenientFormatStringValidation")
   private void assertLocation(
       TextFormatParseInfoTree tree,
       final Descriptor descriptor,
@@ -1775,6 +1787,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)
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/java/internal/JavaVersionTest.java b/java/internal/JavaVersionTest.java
new file mode 100644
index 0000000..eb004d5
--- /dev/null
+++ b/java/internal/JavaVersionTest.java
@@ -0,0 +1,22 @@
+// Test that Kokoro is using the expected version of Java.
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@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/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/test/kotlin/com/google/protobuf/Proto2LiteTest.kt b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt
index c343ccd..50ebbd7 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.EvilNamesProto2OuterClass.EvilNamesProto2
+import `in`.com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.HardKeywordsAllTypesProto2
+import `in`.com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.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 {
@@ -520,6 +525,7 @@
       .isEqualTo(TestUtilLite.getAllLiteExtensionsSet())
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionGetters() {
     testAllExtensionsLite {
@@ -543,6 +549,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testRepeatedExtensionGettersAndSetters() {
     testAllExtensionsLite {
@@ -632,6 +639,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionContains() {
     testAllExtensionsLite {
@@ -663,6 +671,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionClears() {
     testAllExtensionsLite {
@@ -751,6 +760,7 @@
       )
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapGettersAndSetters() {
     testMapLite {
@@ -806,6 +816,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapRemove() {
     testMapLite {
@@ -831,6 +842,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapClear() {
     testMapLite {
@@ -877,7 +889,6 @@
           boolean = 1L
           sealed = "foo"
           interface_ = 1F
-          in_ = 1
           object_ = "foo"
           cachedSize_ = "foo"
           serializedSize_ = true
@@ -903,7 +914,6 @@
           .setBoolean(1L)
           .setSealed("foo")
           .setInterface(1F)
-          .setIn(1)
           .setObject("foo")
           .setCachedSize_("foo")
           .setSerializedSize_(true)
@@ -914,15 +924,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 +954,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 +969,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHardKeywordClears() {
     hardKeywordsAllTypesProto2 {
@@ -970,10 +977,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 ee949dd..bc935c8 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/test/kotlin/com/google/protobuf/Proto2Test.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt
index af797cc..426b367 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.EvilNamesProto2OuterClass.EvilNamesProto2
+import `in`.com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.HardKeywordsAllTypesProto2
+import `in`.com.google.protobuf.kotlin.generator.EvilNamesProto2OuterClass.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 {
@@ -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..e5cdc7d 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,7 @@
 
 package protobuf.kotlin.generator;
 
-option java_package = "com.google.protobuf.kotlin.generator";
+option java_package = "in.com.google.protobuf.kotlin.generator";
 
 message EvilNamesProto2 {
   optional bool initialized = 1;
@@ -61,7 +61,6 @@
   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;
@@ -79,7 +78,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/pom.xml b/java/pom.xml
index 6f1059f..197e7cd 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/pom.xml b/java/protoc/pom.xml
new file mode 100644
index 0000000..b2cd0d5
--- /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.3</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/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/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_wrapper.sh b/kokoro/common/bazel_wrapper.sh
new file mode 100755
index 0000000..bd35396
--- /dev/null
+++ b/kokoro/common/bazel_wrapper.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+# Wrapper for invoking bazel on Kokoro.
+#
+# This script adds 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 is equivalent to the "bazel"
+# command.
+#
+# Example of running directly:
+#   path/to/bazel_wrapper.sh build //...
+#
+# Example of `source`ing:
+#   source path/to/bazel_wrapper.sh
+#   bazel_wrapper build //...
+
+function bazel_wrapper::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_wrapper::kokoro_flags() {
+  [[ -n ${KOKORO_BES_PROJECT_ID:-} ]] || return
+
+  local -a _flags
+  _flags+=(
+    --bes_backend=${KOKORO_BES_BACKEND_ADDRESS:-buildeventservice.googleapis.com}
+    --bes_results_url=https://source.cloud.google.com/results/invocations/
+    --invocation_id=$(bazel_wrapper::gen_invocation_id)
+    --project_id=${KOKORO_BES_PROJECT_ID}  # --bes_instance_name in Bazel 5+
+    --remote_cache=https://storage.googleapis.com/protobuf-bazel-cache
+  )
+  if [[ -n ${KOKORO_BAZEL_AUTH_CREDENTIAL:-} ]]; then
+    _flags+=( --google_credentials=${KOKORO_BAZEL_AUTH_CREDENTIAL} )
+  else
+    _flags+=( --google_default_credentials=true )
+  fi
+
+  echo "${_flags[@]}"
+}
+
+# Runs bazel with Kokoro flags, if appropriate.
+function bazel_wrapper() {
+  local -a _flags
+
+  # We might need to add flags. They need to come after any startup flags and
+  # the command, but before any terminating "--", so copy them into the _flags
+  # variable.
+  until (( ${#@} == 0 )) || [[ $1 == "--" ]]; do
+    _flags+=( "${1}" ); shift
+  done
+
+  # Set the `BAZEL` env variable to override the actual bazel binary to use:
+  ${BAZEL:=bazel} "${_flags[@]}" $(bazel_wrapper::kokoro_flags) "${@}"
+}
+
+# If this script was called directly, run bazel. Otherwise (i.e., this script
+# was `source`d), the sourcing script will call bazel_wrapper themselves.
+(( ${#BASH_SOURCE[@]} == 1 )) && bazel_wrapper "${@}"
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%
copy from kokoro/linux/benchmark/continuous.cfg
copy 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..3770b84
--- /dev/null
+++ b/kokoro/linux/32-bit/test_php.sh
@@ -0,0 +1,51 @@
+#!/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
+}
+
+cmake .
+cmake --build . --target protoc -- -j20
+export PROTOC=$(pwd)/protoc
+
+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
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..0a62cff 100755
--- a/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh
+++ b/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh
@@ -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..b7c8000
--- /dev/null
+++ b/kokoro/linux/bazel.sh
@@ -0,0 +1,44 @@
+#!/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`
+rm -rf $GIT_REPO_ROOT/logs
+
+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
+
+tmpfile=$(mktemp -u)
+
+docker run \
+  --cidfile $tmpfile \
+  -v $GIT_REPO_ROOT:/workspace \
+  $CONTAINER_IMAGE \
+  test \
+  --keep_going \
+  --test_output=streamed \
+  ${ENVS[@]} \
+  $PLATFORM_CONFIG \
+  $BAZEL_EXTRA_FLAGS \
+  $BAZEL_TARGETS
+
+# Save logs for Kokoro
+docker cp \
+  `cat $tmpfile`:/workspace/logs $KOKORO_ARTIFACTS_DIR
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..6d35d8b
--- /dev/null
+++ b/kokoro/linux/bazel/common.cfg
@@ -0,0 +1,16 @@
+# 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: 15
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//src/..."
+}
+
+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..523253d
--- /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
+
+# 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..7d4d7b7 100755
--- a/kokoro/linux/java_linkage_monitor/build.sh
+++ b/kokoro/linux/java_linkage_monitor/build.sh
@@ -4,16 +4,24 @@
 # 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.
+
+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%
rename from kokoro/linux/benchmark/continuous.cfg
rename 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..7e4a798
--- /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/..."
+}
+
+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..5b87fd6
--- /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/..."
+}
+
+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..3ae100c
--- /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/..."
+}
+
+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..ebef928
--- /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/..."
+}
+
+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..7d9e7aa
--- /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/..."
+}
+
+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..decd466
--- /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/..."
+}
+
+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..5133ab5
--- /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/..."
+}
+
+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..9797008
--- /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/..."
+}
+
+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/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..7c21d48 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 //src/... -k --test_output=streamed
diff --git a/kokoro/macos/php7.3_mac/continuous.cfg b/kokoro/macos/cpp/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/cpp/common.cfg
index 9a71745..4bea1cb 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/cpp/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/macos/cpp/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/objectivec_ios_debug/common.cfg
similarity index 61%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/objectivec_ios_debug/common.cfg
index 9a71745..473d545 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/objectivec_ios_debug/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/macos/objectivec_ios_debug/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/objectivec_ios_release/common.cfg
similarity index 60%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/objectivec_ios_release/common.cfg
index 9a71745..3cbfb68 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/objectivec_ios_release/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/macos/objectivec_ios_release/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/objectivec_osx/common.cfg
similarity index 63%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/objectivec_osx/common.cfg
index 9a71745..41bd46a 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/objectivec_osx/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/macos/objectivec_osx/build.sh"
 timeout_mins: 1440
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..2ad4eab
--- /dev/null
+++ b/kokoro/macos/php74/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@7.4
+
+# 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/php7.3_mac/continuous.cfg b/kokoro/macos/php74/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/php74/common.cfg
index 9a71745..cf7e80b 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/php74/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/macos/php74/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/php80/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/php80/common.cfg
index 9a71745..ded43e6 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/php80/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/macos/php80/build.sh"
 timeout_mins: 1440
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 8f99f10..fe3b6be 100755
--- a/kokoro/macos/prepare_build_macos_rc
+++ b/kokoro/macos/prepare_build_macos_rc
@@ -7,37 +7,13 @@
 export HOMEBREW_PREFIX=$(brew --prefix)
 
 ##
-# Remove any pre-existing protobuf installation.
-brew uninstall protobuf
-
-##
-# Select Xcode version
-
-##
 # Select Xcode version
 export DEVELOPER_DIR=/Applications/Xcode_13.3.1.app/Contents/Developer
 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 +23,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..f1ea3aa 100755
--- a/kokoro/macos/python/build.sh
+++ b/kokoro/macos/python/build.sh
@@ -6,7 +6,7 @@
 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/... -k --macos_minimum_os=10.9 --test_output=streamed
diff --git a/kokoro/macos/python/common.cfg b/kokoro/macos/python/common.cfg
new file mode 100644
index 0000000..ac3cbee
--- /dev/null
+++ b/kokoro/macos/python/common.cfg
@@ -0,0 +1,11 @@
+# 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: "**/*"
+  }
+}
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..ae480a5 100755
--- a/kokoro/macos/python_cpp/build.sh
+++ b/kokoro/macos/python_cpp/build.sh
@@ -6,8 +6,7 @@
 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/... -k --macos_minimum_os=10.9 --test_output=streamed --define=use_fast_cpp_protos=true
diff --git a/kokoro/macos/php7.3_mac/continuous.cfg b/kokoro/macos/python_cpp/common.cfg
similarity index 65%
rename from kokoro/macos/php7.3_mac/continuous.cfg
rename to kokoro/macos/python_cpp/common.cfg
index 9a71745..22f4a0e 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/python_cpp/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/macos/python_cpp/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/ruby25/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/ruby25/common.cfg
index 9a71745..b3755e4 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/ruby25/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/macos/ruby25/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/ruby26/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/ruby26/common.cfg
index 9a71745..688f63c 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/ruby26/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/macos/ruby26/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/ruby27/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/ruby27/common.cfg
index 9a71745..b10b455 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/ruby27/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/macos/ruby27/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/ruby30/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/ruby30/common.cfg
index 9a71745..d505117 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/ruby30/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/macos/ruby30/build.sh"
 timeout_mins: 1440
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/php7.3_mac/continuous.cfg b/kokoro/macos/ruby31/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/macos/ruby31/common.cfg
index 9a71745..19e16b3 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/macos/ruby31/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/macos/ruby31/build.sh"
 timeout_mins: 1440
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..933b251
--- /dev/null
+++ b/kokoro/macos/test_php.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+set -eux
+
+pushd php
+rm -rf vendor
+php -v
+php -m
+composer update
+composer test_c
+popd
+
+git clean -fXd
+bazel test //php:conformance_test_c --action_env=PATH --test_env=PATH --test_output=streamed
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/kokoro/release/protoc/linux/build.sh b/kokoro/release/protoc/linux/build.sh
index 44a95aa..ca3ff21 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
 
-sudo apt install -y g++-s390x-linux-gnu
 protoc-artifacts/build-protoc.sh linux s390_64 protoc
 
-# Use docker image to build linux artifacts.
-DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
-docker pull $DOCKER_IMAGE_NAME
+protoc-artifacts/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_64 protoc || {
-  echo "Failed to build protoc for linux + x86_64."
-  exit 1
-}
-
-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
-}
+protoc-artifacts/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 296bd9a..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 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..12d270e 100755
--- a/kokoro/release/ruby/linux/ruby/ruby_build.sh
+++ b/kokoro/release/ruby/linux/ruby/ruby_build.sh
@@ -5,8 +5,10 @@
 # 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
 
 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_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..0b2ba9f
--- /dev/null
+++ b/kokoro/windows/bazel/build.bat
@@ -0,0 +1,33 @@
+@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
+bazel version
+
+@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=streamed --verbose_failures
+
+@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/...  || goto :error
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b 1
diff --git a/kokoro/macos/php7.3_mac/continuous.cfg b/kokoro/windows/bazel/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/windows/bazel/common.cfg
index 9a71745..5978a7a 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/windows/bazel/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/bazel/build.bat"
 timeout_mins: 1440
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..29d012b
--- /dev/null
+++ b/kokoro/windows/cmake/build.bat
@@ -0,0 +1,32 @@
+@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 -ea 0
+md %KOKORO_ARTIFACTS_DIR%\logs -ea 0
+
+cd build
+
+cmake .. ^
+	-G "Visual Studio 15 2017" -A x64 ^
+	-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..5392f9e
--- /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 -ea 0
+md %KOKORO_ARTIFACTS_DIR%\logs -ea 0
+
+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_nmake/build.bat b/kokoro/windows/cmake_nmake/build.bat
new file mode 100644
index 0000000..a080771
--- /dev/null
+++ b/kokoro/windows/cmake_nmake/build.bat
@@ -0,0 +1,34 @@
+@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 -ea 0
+md %KOKORO_ARTIFACTS_DIR%\logs -ea 0
+
+cd build
+
+cmake .. ^
+	-G "NMake Makefiles" ^
+	-DCMAKE_C_COMPILER=cl.exe ^
+	-DCMAKE_CXX_COMPILER=cl.exe ^
+	-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_nmake/common.cfg
similarity index 63%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/windows/cmake_nmake/common.cfg
index 9a71745..3c279fe 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/windows/cmake_nmake/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_nmake/build.bat"
 timeout_mins: 1440
diff --git a/kokoro/windows/cmake_nmake/continuous.cfg b/kokoro/windows/cmake_nmake/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/cmake_nmake/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/cmake_nmake/presubmit.cfg b/kokoro/windows/cmake_nmake/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/cmake_nmake/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..bcd5244
--- /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 -ea 0
+md %KOKORO_ARTIFACTS_DIR%\logs -ea 0
+
+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%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy 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..d8eb2a2
--- /dev/null
+++ b/kokoro/windows/prepare_build_win64.bat
@@ -0,0 +1,16 @@
+@rem Update Chocolatey
+choco upgrade -y --no-progress chocolatey
+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
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/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/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 0e183f2..77a2166 100755
--- a/objectivec/DevTools/full_mac_build.sh
+++ b/objectivec/DevTools/full_mac_build.sh
@@ -8,6 +8,10 @@
 # Some base locations.
 readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")")
 readonly ProtoRootDir="${ScriptDir}/../.."
+readonly BazelFlags="-k --announce_rc --test_output=errors --macos_minimum_os=10.9"
+
+# Invoke with BAZEL=bazelisk to use that instead.
+readonly BazelBin="${BAZEL:=bazel}"
 
 printUsage() {
   NAME=$(basename "${0}")
@@ -24,13 +28,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 +60,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 +80,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 +129,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 +175,23 @@
 
 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
+  "${BazelBin}" test //src/... $BazelFlags
   # Fire off the conformance tests also.
-  cd conformance
-  wrapped_make -j "${NUM_MAKE_JOBS}" test_cpp
-  cd ..
+  "${BazelBin}" test //objectivec:conformance_test $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.
@@ -295,7 +255,7 @@
           -disable-concurrent-destination-testing
       )
       ;;
-    11.* | 12.* | 13.*)
+    11.* | 12.* | 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
@@ -391,9 +351,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/GPBApi.pbobjc.h b/objectivec/GPBApi.pbobjc.h
index 871e908..1848aa6 100644
--- a/objectivec/GPBApi.pbobjc.h
+++ b/objectivec/GPBApi.pbobjc.h
@@ -74,12 +74,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 +115,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 +169,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. */
diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h
index fbe5009..1886ccf 100644
--- a/objectivec/GPBCodedInputStream.h
+++ b/objectivec/GPBCodedInputStream.h
@@ -220,7 +220,7 @@
 /**
  * Moves the limit to the given byte offset starting at the current location.
  *
- * @exception GPBCodedInputStreamException If the requested bytes exceeed the
+ * @exception GPBCodedInputStreamException If the requested bytes exceed the
  *            current limit.
  *
  * @param byteLimit The number of bytes to move the limit, offset to the current
diff --git a/objectivec/GPBFieldMask.pbobjc.h b/objectivec/GPBFieldMask.pbobjc.h
index c4667b4..b7eccff 100644
--- a/objectivec/GPBFieldMask.pbobjc.h
+++ b/objectivec/GPBFieldMask.pbobjc.h
@@ -247,7 +247,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
diff --git a/objectivec/GPBStruct.pbobjc.h b/objectivec/GPBStruct.pbobjc.h
index dd6ab28..ff4eefd 100644
--- a/objectivec/GPBStruct.pbobjc.h
+++ b/objectivec/GPBStruct.pbobjc.h
@@ -87,7 +87,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 +178,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
diff --git a/objectivec/GPBType.pbobjc.h b/objectivec/GPBType.pbobjc.h
index b023050..969219f 100644
--- a/objectivec/GPBType.pbobjc.h
+++ b/objectivec/GPBType.pbobjc.h
@@ -195,17 +195,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 +279,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 +334,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 +385,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
diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m
index b72d0e2..cd0910c 100644
--- a/objectivec/GPBUtilities.m
+++ b/objectivec/GPBUtilities.m
@@ -2248,7 +2248,7 @@
     NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
               @"OneofDescriptor %@ doesn't appear to be for %@ messages.",
               oneof.name, [self class]);
-    GPBFieldDescriptor *firstField = oneof->fields_[0];
+    GPBFieldDescriptor *firstField __unused = oneof->fields_[0];
     NSCAssert(firstField->description_->hasIndex == oneofHasIndex,
               @"Internal error, oneofHasIndex (%d) doesn't match (%d).",
               firstField->description_->hasIndex, oneofHasIndex);
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
index 365fdc3..3d07bf2 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
@@ -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 */,
 			);
@@ -744,7 +752,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 +760,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 +779,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 */,
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
index 03e0580..33cb483 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -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 */,
 			);
@@ -751,7 +759,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 +767,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 +786,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 */,
diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
index c7a8d85..e9c28e1 100644
--- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
@@ -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 */,
 			);
@@ -751,7 +759,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 +767,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 +786,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 */,
diff --git a/objectivec/README.md b/objectivec/README.md
index a0fcd19..25e6b23 100644
--- a/objectivec/README.md
+++ b/objectivec/README.md
@@ -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/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m
index 6cd5a1f..3dd9d3f 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
diff --git a/objectivec/Tests/GPBCodedOuputStreamTests.m b/objectivec/Tests/GPBCodedOutputStreamTests.m
similarity index 99%
rename from objectivec/Tests/GPBCodedOuputStreamTests.m
rename to objectivec/Tests/GPBCodedOutputStreamTests.m
index a9934ac..11fefce 100644
--- a/objectivec/Tests/GPBCodedOuputStreamTests.m
+++ b/objectivec/Tests/GPBCodedOutputStreamTests.m
@@ -33,7 +33,7 @@
 #import "GPBCodedOutputStream_PackagePrivate.h"
 #import "GPBCodedInputStream.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.
diff --git a/objectivec/Tests/GPBConcurrencyTests.m b/objectivec/Tests/GPBConcurrencyTests.m
index daf75e7..1c39317 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;
diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m
index b1ff544..6e83b3f 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,21 +52,21 @@
 
 - (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 {
diff --git a/objectivec/Tests/GPBDictionaryTests+Bool.m b/objectivec/Tests/GPBDictionaryTests+Bool.m
index 4c02144..fbab9ff 100644
--- a/objectivec/Tests/GPBDictionaryTests+Bool.m
+++ b/objectivec/Tests/GPBDictionaryTests+Bool.m
@@ -34,7 +34,7 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
 
 // 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.
diff --git a/objectivec/Tests/GPBDictionaryTests+Int32.m b/objectivec/Tests/GPBDictionaryTests+Int32.m
index 8dafaac..3ffdd21 100644
--- a/objectivec/Tests/GPBDictionaryTests+Int32.m
+++ b/objectivec/Tests/GPBDictionaryTests+Int32.m
@@ -34,7 +34,7 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
 
 // 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.
diff --git a/objectivec/Tests/GPBDictionaryTests+Int64.m b/objectivec/Tests/GPBDictionaryTests+Int64.m
index a603356..9d8a946 100644
--- a/objectivec/Tests/GPBDictionaryTests+Int64.m
+++ b/objectivec/Tests/GPBDictionaryTests+Int64.m
@@ -34,7 +34,7 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
 
 // 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.
diff --git a/objectivec/Tests/GPBDictionaryTests+String.m b/objectivec/Tests/GPBDictionaryTests+String.m
index 8ad1cea..c2fdac3 100644
--- a/objectivec/Tests/GPBDictionaryTests+String.m
+++ b/objectivec/Tests/GPBDictionaryTests+String.m
@@ -34,7 +34,7 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
 
 // 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.
diff --git a/objectivec/Tests/GPBDictionaryTests+UInt32.m b/objectivec/Tests/GPBDictionaryTests+UInt32.m
index f607538..a00dd62 100644
--- a/objectivec/Tests/GPBDictionaryTests+UInt32.m
+++ b/objectivec/Tests/GPBDictionaryTests+UInt32.m
@@ -34,7 +34,7 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
 
 // 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.
diff --git a/objectivec/Tests/GPBDictionaryTests+UInt64.m b/objectivec/Tests/GPBDictionaryTests+UInt64.m
index b5dd91e..e1ac143 100644
--- a/objectivec/Tests/GPBDictionaryTests+UInt64.m
+++ b/objectivec/Tests/GPBDictionaryTests+UInt64.m
@@ -34,7 +34,7 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
 
 // 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.
diff --git a/objectivec/Tests/GPBExtensionRegistryTest.m b/objectivec/Tests/GPBExtensionRegistryTest.m
index b116882..eddefd7 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
diff --git a/objectivec/Tests/GPBMessageTests+Merge.m b/objectivec/Tests/GPBMessageTests+Merge.m
index f895542..8469746 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
diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m
index baad082..cdaea34 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
diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m
index bb63ec3..0427683 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
diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m
index b2c75ba..202d1ef 100644
--- a/objectivec/Tests/GPBMessageTests.m
+++ b/objectivec/Tests/GPBMessageTests.m
@@ -38,10 +38,10 @@
 #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 "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestObjc.pbobjc.h"
+#import "objectivec/Tests/UnittestObjcOptions.pbobjc.h"
+#import "objectivec/Tests/UnittestImport.pbobjc.h"
 
 // Helper class to test KVO.
 @interface GPBKVOTestObserver : NSObject {
diff --git a/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm b/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm
index fb67495..73c52e8 100644
--- a/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm
+++ b/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm
@@ -43,8 +43,8 @@
 // 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
diff --git a/objectivec/Tests/GPBPerfTests.m b/objectivec/Tests/GPBPerfTests.m
index 8dd0ffc..9017468 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
diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m
index 48d75e7..edd143b 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;
 
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..160f0c8 100644
--- a/objectivec/Tests/GPBUnknownFieldSetTest.m
+++ b/objectivec/Tests/GPBUnknownFieldSetTest.m
@@ -32,7 +32,7 @@
 
 #import "GPBUnknownField_PackagePrivate.h"
 #import "GPBUnknownFieldSet_PackagePrivate.h"
-#import "google/protobuf/Unittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
 
 @interface GPBUnknownFieldSet (GPBUnknownFieldSetTest)
 - (void)getTags:(int32_t*)tags;
diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m
index f4a09de..5c3d36f 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
diff --git a/objectivec/Tests/GPBWellKnownTypesTest.m b/objectivec/Tests/GPBWellKnownTypesTest.m
index 592d5af..b7f28a6 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;
@@ -161,9 +161,9 @@
 
   // 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 +171,14 @@
   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,9 +189,9 @@
   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);
 
diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m
index dbeab21..e100667 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
@@ -144,11 +143,11 @@
 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]]
+  // 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:[TestMessageSetExtension2 messageSetExtension]]
+  [[message_set getExtension:[MSetMessageExtension2 messageSetExtension]]
       setStr:@"foo"];
   GPBUnknownField* unknownField =
       [[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease];
@@ -160,26 +159,26 @@
 
   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],
@@ -187,29 +186,29 @@
 }
 
 - (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,19 +216,19 @@
 
   NSData* data = [raw data];
 
-  // Parse as a TestMessageSet and check the contents.
-  TestMessageSet* messageSet =
-      [TestMessageSet parseFromData:data
-                  extensionRegistry:[UnittestMsetRoot extensionRegistry]
+  // Parse as a MSetMessage and check the contents.
+  MSetMessage* messageSet =
+      [MSetMessage parseFromData:data
+                  extensionRegistry:[MSetUnittestMsetRoot extensionRegistry]
                               error:NULL];
 
   XCTAssertEqual(
       [[messageSet
-          getExtension:[TestMessageSetExtension1 messageSetExtension]] i],
+          getExtension:[MSetMessageExtension1 messageSetExtension]] i],
       123);
   XCTAssertEqualObjects(
       [[messageSet
-          getExtension:[TestMessageSetExtension2 messageSetExtension]] str],
+          getExtension:[MSetMessageExtension2 messageSetExtension]] str],
       @"foo");
 
   XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1);
diff --git a/objectivec/Tests/UnitTests-Bridging-Header.h b/objectivec/Tests/UnitTests-Bridging-Header.h
index 46292fc..16d272b 100644
--- a/objectivec/Tests/UnitTests-Bridging-Header.h
+++ b/objectivec/Tests/UnitTests-Bridging-Header.h
@@ -2,5 +2,5 @@
 //  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/stubs/statusor.cc b/objectivec/Tests/any_test.proto
similarity index 78%
rename from src/google/protobuf/stubs/statusor.cc
rename to objectivec/Tests/any_test.proto
index 9c0a178..f2461bf 100644
--- a/src/google/protobuf/stubs/statusor.cc
+++ b/objectivec/Tests/any_test.proto
@@ -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/stubs/statusor.h>
+syntax = "proto3";
 
-#include <google/protobuf/stubs/logging.h>
+package objc.protobuf.tests.any;
 
-namespace google {
-namespace protobuf {
-namespace util {
-namespace statusor_internal {
+import "google/protobuf/any.proto";
 
-void StatusOrHelper::Crash(const Status& status) {
-  GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
-                    << status.ToString();
+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;
 }
-
-}  // namespace statusor_internal
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
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..91e33ce 100644
--- a/objectivec/Tests/unittest_cycle.proto
+++ b/objectivec/Tests/unittest_cycle.proto
@@ -29,7 +29,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 +39,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..aa06a06 100644
--- a/objectivec/Tests/unittest_deprecated.proto
+++ b/objectivec/Tests/unittest_deprecated.proto
@@ -29,7 +29,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..b32b4b4 100644
--- a/objectivec/Tests/unittest_deprecated_file.proto
+++ b/objectivec/Tests/unittest_deprecated_file.proto
@@ -29,7 +29,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..2e09a40 100644
--- a/objectivec/Tests/unittest_extension_chain_a.proto
+++ b/objectivec/Tests/unittest_extension_chain_a.proto
@@ -29,23 +29,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..5cf7ea3 100644
--- a/objectivec/Tests/unittest_extension_chain_b.proto
+++ b/objectivec/Tests/unittest_extension_chain_b.proto
@@ -29,19 +29,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..b07b288 100644
--- a/objectivec/Tests/unittest_extension_chain_c.proto
+++ b/objectivec/Tests/unittest_extension_chain_c.proto
@@ -29,17 +29,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..44d9ee8 100644
--- a/objectivec/Tests/unittest_extension_chain_d.proto
+++ b/objectivec/Tests/unittest_extension_chain_d.proto
@@ -29,21 +29,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..9c7cea8 100644
--- a/objectivec/Tests/unittest_extension_chain_e.proto
+++ b/objectivec/Tests/unittest_extension_chain_e.proto
@@ -29,12 +29,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..33fcaf9 100644
--- a/objectivec/Tests/unittest_extension_chain_f.proto
+++ b/objectivec/Tests/unittest_extension_chain_f.proto
@@ -29,9 +29,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 +41,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..9044e46 100644
--- a/objectivec/Tests/unittest_extension_chain_g.proto
+++ b/objectivec/Tests/unittest_extension_chain_g.proto
@@ -29,13 +29,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/stubs/statusor.cc b/objectivec/Tests/unittest_import_public.proto
similarity index 78%
copy from src/google/protobuf/stubs/statusor.cc
copy to objectivec/Tests/unittest_import_public.proto
index 9c0a178..05969b6 100644
--- a/src/google/protobuf/stubs/statusor.cc
+++ b/objectivec/Tests/unittest_import_public.proto
@@ -28,21 +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/stubs/statusor.h>
+// Author: liujisi@google.com (Pherl Liu)
 
-#include <google/protobuf/stubs/logging.h>
+syntax = "proto2";
 
-namespace google {
-namespace protobuf {
-namespace util {
-namespace statusor_internal {
+package objc.protobuf.tests.public_import;
 
-void StatusOrHelper::Crash(const Status& status) {
-  GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
-                    << status.ToString();
+option objc_class_prefix = "PublicImport";
+
+message Message {
+  optional int32 e = 1;
 }
-
-}  // namespace statusor_internal
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/objectivec/Tests/GPBCompileTest25.m b/objectivec/Tests/unittest_mset.proto
similarity index 68%
rename from objectivec/Tests/GPBCompileTest25.m
rename to objectivec/Tests/unittest_mset.proto
index 7a482b5..9ff070f 100644
--- a/objectivec/Tests/GPBCompileTest25.m
+++ b/objectivec/Tests/unittest_mset.proto
@@ -28,15 +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 = "proto2";
 
-// 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.
+package objc.protobuf.tests.mset;
 
-#import "google/protobuf/UnittestCustomOptions.pbobjc.h"
+option objc_class_prefix = "MSet";
 
+// A message with message_set_wire_format.
+message Message {
+  option message_set_wire_format = true;
+  extensions 4 to max;
+}
 
-// 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;
+message MessageExtension1 {
+  extend Message {
+    optional MessageExtension1 message_set_extension = 1545008;
+  }
+  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..aed200b 100644
--- a/objectivec/Tests/unittest_objc.proto
+++ b/objectivec/Tests/unittest_objc.proto
@@ -30,9 +30,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.
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/objectivec/Tests/GPBCompileTest25.m b/objectivec/Tests/unittest_preserve_unknown_enum.proto
similarity index 66%
copy from objectivec/Tests/GPBCompileTest25.m
copy to objectivec/Tests/unittest_preserve_unknown_enum.proto
index 7a482b5..8cdd58d 100644
--- a/objectivec/Tests/GPBCompileTest25.m
+++ b/objectivec/Tests/unittest_preserve_unknown_enum.proto
@@ -28,15 +28,42 @@
 // (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";
 
-// 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.
+package objc.protobuf.tests.proto3_preserve_unknown_enum;
+option objc_class_prefix = "UnknownEnums";
 
-#import "google/protobuf/UnittestCustomOptions.pbobjc.h"
+enum MyEnum {
+  FOO = 0;
+  BAR = 1;
+  BAZ = 2;
+}
 
+enum MyEnumPlusExtra {
+  E_FOO = 0;
+  E_BAR = 1;
+  E_BAZ = 2;
+  E_EXTRA = 3;
+}
 
-// 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;
+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;
+  }
+}
+
+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..12c2b1c 100644
--- a/objectivec/Tests/unittest_runtime_proto2.proto
+++ b/objectivec/Tests/unittest_runtime_proto2.proto
@@ -29,7 +29,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..d6d4380 100644
--- a/objectivec/Tests/unittest_runtime_proto3.proto
+++ b/objectivec/Tests/unittest_runtime_proto3.proto
@@ -29,7 +29,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..0fb9f4c 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 dfb0976..1f31466 100644
--- a/php/BUILD.bazel
+++ b/php/BUILD.bazel
@@ -3,19 +3,102 @@
 # See also code generation logic under /src/google/protobuf/compiler/php.
 
 load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:internal_shell.bzl", "inline_sh_binary")
+load("//conformance:defs.bzl", "conformance_test")
+
+filegroup(
+    name = "source_files",
+    visibility = [
+        "//conformance:__pkg__",
+        "//php:__pkg__",
+    ],
+    srcs = glob([
+        "ext/google/protobuf/*.h",
+        "ext/google/protobuf/*.c",
+        "src/GPBMetadata/Google/Protobuf/**/*.php",
+        "src/Google/Protobuf/**/*.php",
+    ]) + [
+        "composer.json",
+        "ext/google/protobuf/wkt.inc",
+        "ext/google/protobuf/config.m4",
+        "ext/google/protobuf/package.xml",
+    ],
+)
+
+################################################################################
+# PHP Extension
+################################################################################
+
+inline_sh_binary(
+    name = "build_extension",
+    cmd = """
+        mkdir -p php/ext/google/protobuf/third_party/utf8_range
+        cp third_party/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",
+        "//third_party/utf8_range:all_files",
+    ],
+    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"],
+    }),
+)
+
+################################################################################
+# 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",
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/message.c b/php/ext/google/protobuf/message.c
index 55f4f4d..83c51a4 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -601,7 +601,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);
diff --git a/php/generate_descriptor_protos.sh b/php/generate_descriptor_protos.sh
index 9feaa96..1a600ab 100755
--- a/php/generate_descriptor_protos.sh
+++ b/php/generate_descriptor_protos.sh
@@ -5,6 +5,12 @@
 
 set -e
 
+PROTOC=$(realpath protoc)
+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 +20,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..565c7ec 100755
--- a/php/generate_test_protos.sh
+++ b/php/generate_test_protos.sh
@@ -2,19 +2,15 @@
 
 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
+PROTOC=$(pwd)/protoc
+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 +19,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/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/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..dc42aa3 100755
--- a/php/tests/compile_extension.sh
+++ b/php/tests/compile_extension.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-set -e
+set -ex
 
 cd $(dirname $0)/..
 
diff --git a/pkg/BUILD.bazel b/pkg/BUILD.bazel
index ecce255..812224c 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,33 @@
     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:
+        ":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_protos": "protobuf_test_protos",
+        "//src/google/protobuf:lite_test_srcs": "protobuf_lite_test",
+        "//src/google/protobuf:lite_test_protos": "protobuf_lite_test_protos",
+        "//src/google/protobuf/compiler:test_srcs": "compiler_test",
+        ":compiler_annotation_test_util": "annotation_test_util",
+        ":compiler_mock_code_generator": "mock_code_generator",
+        "//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",
+        ":testinglib": "testing",
+        "//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 +344,13 @@
         "//build_defs:config_msvc": [],
         "//conditions:default": ["-lpthread"],
     }),
+    tags = ["manual"],
     deps = [
-        "//:protobuf_lite",
+        "//src/google/protobuf:arena",
+        "//src/google/protobuf:protobuf_lite",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/io:io_win32",
+        "//src/google/protobuf/stubs:lite",
     ],
 )
 
@@ -362,12 +363,88 @@
             "-lpthread",
         ],
     }),
+    tags = ["manual"],
     deps = [
-        "//:protobuf",
-        "//:protobuf_lite",
+        "//src/google/protobuf",
+        "//src/google/protobuf:arena",
+        "//src/google/protobuf:protobuf_lite",
+        "//src/google/protobuf/compiler:importer",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/io:gzip_stream",
+        "//src/google/protobuf/io:io_win32",
+        "//src/google/protobuf/io:printer",
+        "//src/google/protobuf/io:tokenizer",
+        "//src/google/protobuf/io:zero_copy_sink",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/stubs:lite",
+        "//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",
+        "//src/google/protobuf/util/internal:datapiece",
+        "//src/google/protobuf/util/internal:default_value",
+        "//src/google/protobuf/util/internal:field_mask_utility",
+        "//src/google/protobuf/util/internal:json",
+        "//src/google/protobuf/util/internal:object_writer",
+        "//src/google/protobuf/util/internal:protostream",
+        "//src/google/protobuf/util/internal:type_info",
+        "//src/google/protobuf/util/internal:utility",
     ],
 )
 
+cc_dist_library(
+    name = "protoc",
+    tags = ["manual"],
+    deps = [
+        "//src/google/protobuf/compiler:code_generator",
+        "//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",
+    ],
+)
+
+cc_dist_library(
+    name = "lite_test_util",
+    testonly = 1,
+    tags = ["manual"],
+    deps = ["//src/google/protobuf:lite_test_util"],
+)
+
+cc_dist_library(
+    name = "test_util",
+    testonly = 1,
+    tags = ["manual"],
+    deps = ["//src/google/protobuf:test_util"],
+)
+
+cc_dist_library(
+    name = "compiler_annotation_test_util",
+    testonly = 1,
+    tags = ["manual"],
+    deps = ["//src/google/protobuf/compiler:annotation_test_util"],
+)
+
+cc_dist_library(
+    name = "compiler_mock_code_generator",
+    testonly = 1,
+    tags = ["manual"],
+    deps = ["//src/google/protobuf/compiler:mock_code_generator"],
+)
+
+cc_dist_library(
+    name = "testinglib",
+    testonly = 1,
+    tags = ["manual"],
+    deps = ["//src/google/protobuf/testing"],
+)
+
 ################################################################################
 # Distribution sources
 ################################################################################
diff --git a/pkg/build_systems.bzl b/pkg/build_systems.bzl
index 753d285..cb8ad11 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,17 +14,10 @@
         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",
         ],
     )
 
@@ -31,21 +25,6 @@
 # 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 +44,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 +112,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 +125,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)
@@ -343,6 +283,9 @@
         entries = "\n".join(["  %s%s" % (prefix, f) 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 +304,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 +324,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..383979e 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,207 @@
     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])
+
+    files = []
+    for target in targets:
+        files.extend(target.files.to_list())
+    return files
+
+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 = _flatten_target_files(getattr(rule_attr, "hdrs", depset())),
+        textual_hdrs = _flatten_target_files(getattr(
+            rule_attr,
+            "textual_hdrs",
+            depset(),
+        )),
+        internal_hdrs = depset(internal_hdrs),
+        srcs = depset(srcs),
+    )]
+
+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")]),
+  # )
+""",
+    implementation = _cc_file_list_aspect_impl,
+)
+
+################################################################################
+# Rule impl
+################################################################################
+
+def _collect_inputs(deps):
+    """Collects files from a list of immediate deps.
+
+    This rule collects source files and linker inputs for C++ deps. Only
+    these immediate deps are considered, not transitive 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. These will be treated as the "inputs,"
+          but not the transitive deps.
+
+    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),
+        ),
+    )
+
+# 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 = _collect_inputs(ctx.attr.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 +335,7 @@
 
     return [
         DefaultInfo(files = depset(outputs)),
+        inputs.cc_file_list,
     ]
 
 cc_dist_library = rule(
@@ -214,6 +381,7 @@
                    "Only these targets' compilation outputs will be " +
                    "included (i.e., the transitive dependencies are not " +
                    "included in the output)."),
+            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..8ed2cfa 100644
--- a/protobuf.bzl
+++ b/protobuf.bzl
@@ -1,5 +1,6 @@
 load("@bazel_skylib//lib:versions.bzl", "versions")
-load("@rules_cc//cc:defs.bzl", "cc_library")
+load("@bazel_skylib//lib:collections.bzl", "collections")
+load("@rules_cc//cc:defs.bzl", "cc_library", "objc_library")
 load("@rules_proto//proto:defs.bzl", "ProtoInfo")
 load("@rules_python//python:defs.bzl", "py_library", "py_test")
 
@@ -37,20 +38,23 @@
         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,28 @@
         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 +95,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 +137,27 @@
                 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 +210,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 +235,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 +393,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 +493,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 +515,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 +531,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 +548,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 afb1f1e..427f29f 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.2.1/bazel-skylib-1.2.1.tar.gz",
+                "https://github.com/bazelbuild/bazel-skylib/releases/download/1.2.1/bazel-skylib-1.2.1.tar.gz",
             ],
+            sha256 = "f7be3474d42aae265405a592bb7da8e171919d74c16f082a5457840f06054728",
         )
 
     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"):
@@ -106,14 +107,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 = "333722e94b35c26b9eb48bd7e471235374ab3737",
-            sha256 = "f973aefa29d4191aad76cd1ba74ee3be4d2161b6c95d73c137f82560983912c6",
+            commit = "5485645125ba3783ae2b597bd7b77679721cb1c6",
+            sha256 = "86de85c58eb3cb04b0987a7642ce84e55629f704ab4a9a0210a660a1115f1dd0",
         )
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
index 8fc3669..5511f9a 100644
--- a/protoc-artifacts/README.md
+++ b/protoc-artifacts/README.md
@@ -43,13 +43,13 @@
 ## Building from a freshly checked-out source
 
 If you just checked out the Protobuf source from github, you need to
-generate the configure script.
+pull in any submodules.
 
 Under the protobuf project directory:
 
 
 ```
-$ ./autogen.sh
+git submodule update --init --recursive
 ```
 
 ### Build the artifact for each platform
diff --git a/protoc-artifacts/build-protoc.sh b/protoc-artifacts/build-protoc.sh
index 4602842..d304d5f 100755
--- a/protoc-artifacts/build-protoc.sh
+++ b/protoc-artifacts/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/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
index 8e81909..19e700d 100644
--- a/protoc-artifacts/pom.xml
+++ b/protoc-artifacts/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>com.google</groupId>
     <artifactId>google</artifactId>
-    <version>1</version>
+    <version>5</version>
   </parent>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protoc</artifactId>
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..118bb4d
--- /dev/null
+++ b/python/BUILD.bazel
@@ -0,0 +1,455 @@
+# 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("//: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")
+
+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",
+    ],
+)
+
+py_test(
+    name = "descriptor_database_test",
+    srcs = ["google/protobuf/internal/descriptor_database_test.py"],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "descriptor_pool_test",
+    srcs = ["google/protobuf/internal/descriptor_pool_test.py"],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "descriptor_test",
+    srcs = ["google/protobuf/internal/descriptor_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "generator_test",
+    srcs = ["google/protobuf/internal/generator_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "import_test",
+    srcs = ["google/protobuf/internal/import_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "json_format_test",
+    srcs = ["google/protobuf/internal/json_format_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "keywords_test",
+    srcs = ["google/protobuf/internal/keywords_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "message_factory_test",
+    srcs = ["google/protobuf/internal/message_factory_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "message_test",
+    srcs = ["google/protobuf/internal/message_test.py"],
+    data = glob(["testdata/golden_pickle_*"]) + [
+        "//src/google/protobuf:testdata",
+    ],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "proto_builder_test",
+    srcs = ["google/protobuf/internal/proto_builder_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "reflection_test",
+    srcs = ["google/protobuf/internal/reflection_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "service_reflection_test",
+    srcs = ["google/protobuf/internal/service_reflection_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "symbol_database_test",
+    srcs = ["google/protobuf/internal/symbol_database_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "text_encoding_test",
+    srcs = ["google/protobuf/internal/text_encoding_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "text_format_test",
+    srcs = ["google/protobuf/internal/text_format_test.py"],
+    data = ["//src/google/protobuf:testdata"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "unknown_fields_test",
+    srcs = ["google/protobuf/internal/unknown_fields_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "well_known_types_test",
+    srcs = ["google/protobuf/internal/well_known_types_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+py_test(
+    name = "wire_format_test",
+    srcs = ["google/protobuf/internal/wire_format_test.py"],
+    imports = ["."],
+    deps = [":python_test_lib"],
+)
+
+cc_library(
+    name = "proto_api",
+    hdrs = ["google/protobuf/proto_api.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//external:python_headers",
+    ],
+)
+
+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({
+        ":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({
+        ":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",
+        "mox.py",
+        "python_version.py",
+        "release.sh",
+        "setup.cfg",
+        "setup.py",
+        "stubout.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/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index f5a0caa..997f6db 100644
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -873,11 +873,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 +1021,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/api_implementation.py b/python/google/protobuf/internal/api_implementation.py
index 7458648..3b81f27 100644
--- a/python/google/protobuf/internal/api_implementation.py
+++ b/python/google/protobuf/internal/api_implementation.py
@@ -151,12 +151,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/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py
index 9e451b4..efd909a 100644
--- a/python/google/protobuf/internal/descriptor_pool_test.py
+++ b/python/google/protobuf/internal/descriptor_pool_test.py
@@ -33,7 +33,6 @@
 __author__ = 'matthewtoia@google.com (Matt Toia)'
 
 import copy
-import os
 import unittest
 import warnings
 
@@ -415,7 +414,6 @@
     field = file_json.message_types_by_name['class'].fields_by_name['int_field']
     self.assertEqual(field.json_name, 'json_int')
 
-
   def testEnumDefaultValue(self):
     """Test the default value of enums which don't start at zero."""
     def _CheckDefaultValue(file_descriptor):
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index 6a8532c..3af2bdc 100644
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -118,6 +118,30 @@
   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 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')
@@ -595,6 +619,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 +641,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 +661,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
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_test.py b/python/google/protobuf/internal/message_test.py
index bd1df8c..3c604dd 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)'
@@ -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:
@@ -1766,6 +1769,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.
@@ -2229,7 +2245,7 @@
 
   def testMapItems(self):
     # Map items used to have strange behaviors when use c extension. Because
-    # [] may reorder the map and invalidate any exsting iterators.
+    # [] may reorder the map and invalidate any existing iterators.
     # TODO(jieluo): Check if [] reordering the map is a bug or intended
     # behavior.
     msg = map_unittest_pb2.TestMap()
@@ -2453,6 +2469,26 @@
     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)
+
 
 
 
diff --git a/python/google/protobuf/internal/python_protobuf.cc b/python/google/protobuf/internal/python_protobuf.cc
index 26e3a8b..95c6d2b 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/python_protobuf.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 18b784e..996ef65 100644
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -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 }')
@@ -2443,5 +2484,6 @@
     self.assertEqual('repeated_int32: [1]\n', output)
 
 
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py
index 5024ed8..f35a432 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
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index 76c6802..0fe6a4f 100644
--- 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..fc97b0f 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();
 }
@@ -1741,7 +1796,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..db14ae6 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -30,19 +30,22 @@
 
 // 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"
 
 #define PyString_AsStringAndSize(ob, charpp, sizep)              \
   (PyUnicode_Check(ob)                                           \
@@ -246,7 +249,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 +273,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 +289,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 +310,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 +332,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 +353,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 +375,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 +395,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 +415,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..7990e95 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 "google/protobuf/stubs/strutil.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)) {
+      HasSuffixString(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;
@@ -1337,7 +1341,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 +1390,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 +1575,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 +1885,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 +1977,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 +2376,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 +2677,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 +2700,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 +3037,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 +3046,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..5cc48e7 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/wire_format_lite.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/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..9f27f26 100644
--- a/python/google/protobuf/pyext/unknown_fields.cc
+++ b/python/google/protobuf/pyext/unknown_fields.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/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 "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"
 
 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..2b79428 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):
@@ -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:
@@ -978,9 +984,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 +1006,18 @@
 
     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(';')
 
+    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."""
@@ -1160,105 +1173,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 +1318,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 +1352,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 +1606,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()
diff --git a/python/internal.bzl b/python/internal.bzl
new file mode 100644
index 0000000..e9bcb27
--- /dev/null
+++ b/python/internal.bzl
@@ -0,0 +1,108 @@
+# 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
+    )
diff --git a/python/python_version.py b/python/python_version.py
new file mode 100644
index 0000000..5bf8d21
--- /dev/null
+++ b/python/python_version.py
@@ -0,0 +1,52 @@
+# 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 that Kokoro is using the expected version of python."""
+
+import os
+import sys
+import unittest
+
+
+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..7a55359 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -29,10 +29,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 +207,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 +224,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 +284,37 @@
     # 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']
+          # 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 +339,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 +381,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(
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..d014402 100644
--- a/ruby/BUILD.bazel
+++ b/ruby/BUILD.bazel
@@ -3,30 +3,180 @@
 # See also code generation logic under /src/google/protobuf/compiler/ruby.
 
 load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+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",
+        "//third_party/utf8_range:all_files",
+    ] + 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"],
+    }),
+)
+
+################################################################################
+# 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..89a00e1 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")
@@ -153,13 +153,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..5cc4533 100755
--- a/ruby/ext/google/protobuf_c/extconf.rb
+++ b/ruby/ext/google/protobuf_c/extconf.rb
@@ -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/message.c b/ruby/ext/google/protobuf_c/message.c
index 6b8bbaa..b118785 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) {
@@ -1201,36 +1202,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;
 }
 
@@ -1392,11 +1365,41 @@
   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/internal.bzl b/ruby/internal.bzl
new file mode 100644
index 0000000..74a2d10
--- /dev/null
+++ b/ruby/internal.bzl
@@ -0,0 +1,35 @@
+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",
+            "//third_party/utf8_range:all_files",
+        ],
+        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..6e9c612 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=" \
+    -k --test_output=streamed \
+    --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..a34c021
--- /dev/null
+++ b/src/BUILD.bazel
@@ -0,0 +1,43 @@
+################################################################################
+# 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("//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",
+        "//src/google/protobuf/util/internal: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",
+)
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 3a6ecdc..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:6: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..3592f4f 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..220ffe0
--- /dev/null
+++ b/src/file_lists.cmake
@@ -0,0 +1,848 @@
+# 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.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/api.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena.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/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.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_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/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/source_context.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.pb.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/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/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/wire_format_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.cc
+)
+
+# //pkg:protobuf
+set(libprotobuf_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/api.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena.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/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/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/field_mask.pb.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/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/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/source_context.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.pb.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/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/stubs/stl_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringprintf.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil.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/internal/datapiece.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/default_value_objectwriter.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/error_listener.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/field_mask_utility.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_escaping.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_objectwriter.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_stream_parser.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/location_tracker.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/object_location_tracker.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/object_source.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/object_writer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/proto_writer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectsource.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectwriter.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/structured_objectwriter.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/type_info.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/utility.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
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.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_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/bytestream.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.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/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_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/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/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/stubs/stl_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringprintf.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil.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/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/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
+)
+
+# //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_names.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/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/objectivec_enum.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_extension.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_file.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/objectivec/objectivec_map_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.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: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_lite.h
+)
+
+# //pkg:test_util
+set(test_util_srcs
+  ${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/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/test_util_lite.h
+  ${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_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_protos
+set(protobuf_test_protos_proto_srcs
+  ${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:test_protos
+set(protobuf_test_protos_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_test.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_proto2_unittest.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_unittest.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_arena.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_custom_options.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_drop_unknown_fields.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_embed_optimize_for.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_empty.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_enormous_descriptor.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_enum.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite_imports_nonlite.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset_wire_format.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_field_presence.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_generic_services.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_optimize_for.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum2.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena_lite.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_lite.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_optional.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_well_known_types.proto.pb.cc
+)
+
+# //src/google/protobuf:test_protos
+set(protobuf_test_protos_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_test.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_proto2_unittest.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_unittest.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_arena.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_custom_options.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_drop_unknown_fields.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_embed_optimize_for.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_empty.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_enormous_descriptor.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_enum.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite_imports_nonlite.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset_wire_format.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_field_presence.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_generic_services.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_optimize_for.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum2.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena_lite.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_lite.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_optional.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_well_known_types.proto.pb.h
+)
+
+# //src/google/protobuf:test_protos
+set(protobuf_test_protos_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_protos-descriptor-set.proto.bin
+)
+
+# //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_protos
+set(protobuf_lite_test_protos_proto_srcs
+  ${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:lite_test_protos
+set(protobuf_lite_test_protos_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_unittest.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_lite.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public_lite.proto.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite.proto.pb.cc
+)
+
+# //src/google/protobuf:lite_test_protos
+set(protobuf_lite_test_protos_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_unittest.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_lite.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public_lite.proto.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite.proto.pb.h
+)
+
+# //src/google/protobuf:lite_test_protos
+set(protobuf_lite_test_protos_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/lite_test_protos-descriptor-set.proto.bin
+)
+
+# //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/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
+)
+
+# //pkg:compiler_annotation_test_util
+set(annotation_test_util_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.cc
+)
+
+# //pkg:compiler_annotation_test_util
+set(annotation_test_util_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.h
+)
+
+# //pkg:compiler_mock_code_generator
+set(mock_code_generator_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/mock_code_generator.cc
+)
+
+# //pkg:compiler_mock_code_generator
+set(mock_code_generator_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/mock_code_generator.h
+)
+
+# //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
+)
+
+# //pkg:testinglib
+set(testing_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/googletest.cc
+)
+
+# //pkg:testinglib
+set(testing_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/googletest.h
+)
+
+# //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/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
+)
+
+# //src/google/protobuf/util:test_proto_srcs
+set(util_test_protos_files
+  ${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
+)
+
+# //src/google/protobuf/stubs:test_srcs
+set(stubs_test_files
+  ${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/stringprintf_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/structurally_valid_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil_unittest.cc
+)
diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel
new file mode 100644
index 0000000..7a6fc12
--- /dev/null
+++ b/src/google/protobuf/BUILD.bazel
@@ -0,0 +1,1161 @@
+################################################################################
+# 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("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS")
+
+package(
+    default_visibility = [
+        "//:__pkg__",  # "public" targets are alias rules in //.
+    ],
+)
+
+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",
+)
+
+# 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",
+    srcs = [
+        "arena.cc",
+        "arena_config.cc",
+    ],
+    hdrs = [
+        "arena.h",
+        "arena_config.h",
+        "arena_impl.h",
+        "arenaz_sampler.h",
+    ],
+    include_prefix = "google/protobuf",
+    visibility = [
+        "//:__subpackages__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    deps = [
+        "//src/google/protobuf/stubs:lite",
+        "@com_google_absl//absl/synchronization",
+    ],
+)
+
+cc_library(
+    name = "protobuf_lite",
+    srcs = [
+        "any_lite.cc",
+        "arena_config.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_config.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",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs:lite",
+        "@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",
+    ],
+)
+
+cc_library(
+    name = "protobuf",
+    srcs = [
+        "any.cc",
+        "any.pb.cc",
+        "api.pb.cc",
+        "descriptor.cc",
+        "descriptor.pb.cc",
+        "descriptor_database.cc",
+        "duration.pb.cc",
+        "dynamic_message.cc",
+        "empty.pb.cc",
+        "extension_set_heavy.cc",
+        "field_mask.pb.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",
+        "source_context.pb.cc",
+        "struct.pb.cc",
+        "text_format.cc",
+        "timestamp.pb.cc",
+        "type.pb.cc",
+        "unknown_field_set.cc",
+        "wire_format.cc",
+        "wrappers.pb.cc",
+    ],
+    hdrs = [
+        "any.pb.h",
+        "api.pb.h",
+        "descriptor.h",
+        "descriptor.pb.h",
+        "descriptor_database.h",
+        "duration.pb.h",
+        "dynamic_message.h",
+        "empty.pb.h",
+        "field_access_listener.h",
+        "field_mask.pb.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",
+        "source_context.pb.h",
+        "struct.pb.h",
+        "text_format.h",
+        "timestamp.pb.h",
+        "type.pb.h",
+        "unknown_field_set.h",
+        "wire_format.h",
+        "wrappers.pb.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf",
+    linkopts = LINK_OPTS,
+    visibility = [
+        "//:__pkg__",
+        "//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",
+    ],
+)
+
+# 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__",
+    ],
+)
+
+proto_library(
+    name = "lite_test_protos",
+    srcs = [
+        "map_lite_unittest.proto",
+        "unittest_import_lite.proto",
+        "unittest_import_public_lite.proto",
+        "unittest_lite.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",
+    ],
+)
+
+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__",
+    ],
+)
+
+proto_library(
+    name = "test_messages_proto3_proto",
+    srcs = ["test_messages_proto3.proto"],
+    strip_import_prefix = "/src",
+    visibility = [
+        "//:__pkg__",
+        "//conformance:__pkg__",
+    ],
+    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_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_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_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..2aa32b8 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -52,6 +52,8 @@
   ~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_),
 };
@@ -71,7 +73,7 @@
   "anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT"
   "ypesb\006proto3"
   ;
-static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
+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,
     "google/protobuf/any.proto",
@@ -98,7 +100,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);
 }
@@ -365,4 +367,4 @@
 #if defined(__llvm__)
   #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 ac51c9b..8075234 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,19 +19,19 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -113,7 +113,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 +130,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 +139,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);
@@ -194,7 +194,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:
@@ -294,11 +294,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() {
@@ -307,9 +307,9 @@
 }
 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
@@ -344,11 +344,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() {
@@ -357,9 +357,9 @@
 }
 inline void Any::set_allocated_value(std::string* value) {
   if (value != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.value_.SetAllocated(value, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -380,5 +380,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto_2epb_2eh
diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc
index f283a31..fb812d7 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 "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/any.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.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);
 }
 
-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..7e6ecb2 100644
--- a/src/google/protobuf/any_test.cc
+++ b/src/google/protobuf/any_test.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 <google/protobuf/any_test.pb.h>
-#include <google/protobuf/unittest.pb.h>
+#include "google/protobuf/any_test.pb.h"
+#include "google/protobuf/unittest.pb.h"
 #include <gtest/gtest.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 {
@@ -191,4 +192,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..080a47e 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -85,6 +85,8 @@
   ~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_),
@@ -98,6 +100,8 @@
   ~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_),
@@ -111,13 +115,15 @@
   ~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)},
+  { 15, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Method)},
+  { 30, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Mixin)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
@@ -151,7 +157,7 @@
   &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
   &::descriptor_table_google_2fprotobuf_2ftype_2eproto,
 };
-static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fapi_2eproto_once;
+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,
     "google/protobuf/api.proto",
@@ -373,7 +379,7 @@
       // .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);
+          uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val));
         } else
@@ -800,7 +806,7 @@
       // .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);
+          uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val));
         } else
@@ -1306,4 +1312,4 @@
 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 348bac8..726c959 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,21 +19,21 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -169,7 +169,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:
@@ -429,7 +429,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:
@@ -667,7 +667,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:
@@ -766,11 +766,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() {
@@ -779,9 +779,9 @@
 }
 inline void Api::set_allocated_name(std::string* name) {
   if (name != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -893,11 +893,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() {
@@ -906,9 +906,9 @@
 }
 inline void Api::set_allocated_version(std::string* version) {
   if (version != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.version_.SetAllocated(version, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -942,9 +942,9 @@
   }
   _impl_.source_context_ = source_context;
   if (source_context) {
-    
+
   } else {
-    
+
   }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.source_context)
 }
@@ -996,9 +996,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 +1092,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() {
@@ -1105,9 +1105,9 @@
 }
 inline void Method::set_allocated_name(std::string* name) {
   if (name != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -1142,11 +1142,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() {
@@ -1155,9 +1155,9 @@
 }
 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
@@ -1180,7 +1180,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 +1212,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() {
@@ -1225,9 +1225,9 @@
 }
 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
@@ -1250,7 +1250,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 +1343,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() {
@@ -1356,9 +1356,9 @@
 }
 inline void Mixin::set_allocated_name(std::string* name) {
   if (name != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -1393,11 +1393,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() {
@@ -1406,9 +1406,9 @@
 }
 inline void Mixin::set_allocated_root(std::string* root) {
   if (root != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.root_.SetAllocated(root, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -1433,5 +1433,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto_2epb_2eh
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 6ba508a..0eb8cc9 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,17 +37,18 @@
 #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_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 {
@@ -104,107 +105,307 @@
   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;
+SerialArena::SerialArena(Block* b, ThreadSafeArena& parent)
+    : parent_(parent), space_allocated_(b->size()) {
+  set_head(b);
+  set_ptr(b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize));
+  limit_ = b->Pointer(b->size() & static_cast<size_t>(-8));
 }
 
-SerialArena* SerialArena::New(Memory mem, void* owner,
-                              ThreadSafeArenaStats* stats) {
+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);
+  ThreadSafeArenaStats::RecordAllocateStats(parent.arena_stats_.MutableStats(),
+                                            /*used=*/0, /*allocated=*/mem.size,
+                                            /*wasted=*/0);
   auto b = new (mem.ptr) Block{nullptr, mem.size};
-  return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, owner, stats);
+  return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, parent);
 }
 
 template <typename Deallocator>
 SerialArena::Memory SerialArena::Free(Deallocator deallocator) {
-  Block* b = head_;
-  Memory mem = {b, b->size};
+  Block* b = head();
+  Memory mem = {b, b->size()};
   while (b->next) {
     b = b->next;  // We must first advance before deleting this block
     deallocator(mem);
-    mem = {b, b->size};
+    mem = {b, b->size()};
   }
   return mem;
 }
 
 PROTOBUF_NOINLINE
-std::pair<void*, SerialArena::CleanupNode*>
-SerialArena::AllocateAlignedWithCleanupFallback(
-    size_t n, const AllocationPolicy* policy) {
-  AllocateNewBlock(n + kCleanupSize, policy);
-  return 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) {
+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);
+}
+
+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) {
   // Sync limit to block
-  head_->start = reinterpret_cast<CleanupNode*>(limit_);
+  head()->cleanup_nodes = limit_;
 
   // Record how much used in this block.
-  size_t used = ptr_ - head_->Pointer(kBlockHeaderSize);
-  size_t wasted = head_->size - used;
-  space_used_ += used;
+  size_t used = static_cast<size_t>(ptr() - head()->Pointer(kBlockHeaderSize));
+  size_t wasted = 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(), 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);
+  set_head(new (mem.ptr) Block{head(), mem.size});
+  set_ptr(head()->Pointer(kBlockHeaderSize));
+  limit_ = head()->Pointer(head()->size());
 
 #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_;
+  // 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 uint64_t current_block_size = head()->size();
+  uint64_t space_used = std::min(
+      static_cast<uint64_t>(
+          ptr() - const_cast<Block*>(head())->Pointer(kBlockHeaderSize)),
+      current_block_size);
+  space_used += space_used_.load(std::memory_order_relaxed);
   // Remove the overhead of the SerialArena itself.
   space_used -= ThreadSafeArena::kSerialArenaSize;
   return space_used;
 }
 
 void SerialArena::CleanupList() {
-  Block* b = head_;
-  b->start = reinterpret_cast<CleanupNode*>(limit_);
+  Block* b = head();
+  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 = reinterpret_cast<char*>(
+        b->Pointer(b->size() & static_cast<size_t>(-8)));
+    char* it = reinterpret_cast<char*>(b->cleanup_nodes);
+    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 {
+//   SerialArenaChunk* next_chunk;
+//   const uint32_t capacity;
+//   std::atomic<uint32_t> size;
+//   std::atomic<void*> ids[];
+//   std::atomic<SerialArena*> arenas[];
+// };
+//
+// where the size of "ids" and "arenas" is determined at runtime; hence the use
+// of Layout.
+class ThreadSafeArena::SerialArenaChunk {
+ public:
+  explicit SerialArenaChunk(uint32_t capacity) {
+    set_next(nullptr);
+    set_capacity(capacity);
+    new (&size()) std::atomic<uint32_t>{0};
+
+    for (unsigned i = 0; i < capacity; ++i) {
+      new (&id(i)) std::atomic<void*>{nullptr};
+    }
+
+    for (unsigned i = 0; i < capacity; ++i) {
+      new (&arena(i)) std::atomic<void*>{nullptr};
+    }
+  }
+
+  SerialArenaChunk(uint32_t capacity, void* me, SerialArena* serial) {
+    set_next(nullptr);
+    set_capacity(capacity);
+    new (&size()) std::atomic<uint32_t>{1};
+
+    new (&id(0)) std::atomic<void*>{me};
+    for (unsigned i = 1; i < capacity; ++i) {
+      new (&id(i)) std::atomic<void*>{nullptr};
+    }
+
+    new (&arena(0)) std::atomic<SerialArena*>{serial};
+    for (unsigned i = 1; i < capacity; ++i) {
+      new (&arena(i)) std::atomic<void*>{nullptr};
+    }
+  }
+
+  // next_chunk
+  const SerialArenaChunk* next_chunk() const {
+    return *layout_type::Partial().Pointer<kNextChunk>(ptr());
+  }
+  SerialArenaChunk* next_chunk() {
+    return *layout_type::Partial().Pointer<kNextChunk>(ptr());
+  }
+  void set_next(SerialArenaChunk* next_chunk) {
+    *layout_type::Partial().Pointer<kNextChunk>(ptr()) = next_chunk;
+  }
+
+  // capacity
+  uint32_t capacity() const {
+    return *layout_type::Partial(1u).Pointer<kCapacity>(ptr());
+  }
+  void set_capacity(uint32_t capacity) {
+    *layout_type::Partial(1u).Pointer<kCapacity>(ptr()) = 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(unsigned 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());
+  }
+  std::atomic<SerialArena*>& arena(unsigned 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_relaxed);
+    return true;
+  }
+
+  constexpr static size_t AllocSize(size_t n) { return Layout(n).AllocSize(); }
+
+ private:
+  constexpr static int kNextChunk = 0;
+  constexpr static int kCapacity = 1;
+  constexpr static int kSize = 2;
+  constexpr static int kIds = 3;
+  constexpr static int kArenas = 4;
+
+  using layout_type = absl::container_internal::Layout<
+      SerialArenaChunk*, uint32_t, std::atomic<uint32_t>, std::atomic<void*>,
+      std::atomic<SerialArena*>>;
+
+  const char* ptr() const { return reinterpret_cast<const char*>(this); }
+  char* ptr() { return reinterpret_cast<char*>(this); }
+
+  std::atomic<uint32_t>& size() {
+    return *layout_type::Partial(1u, 1u).Pointer<kSize>(ptr());
+  }
+
+  const std::atomic<uint32_t>& size() const {
+    return *layout_type::Partial(1u, 1u).Pointer<kSize>(ptr());
+  }
+
+  // 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(
+        /*next_chunk*/ 1,
+        /*capacity*/ 1,
+        /*size*/ 1,
+        /*ids*/ n,
+        /*arenas*/ n);
+  }
+};
+
 
 ThreadSafeArena::CacheAlignedLifecycleIdGenerator
     ThreadSafeArena::lifecycle_id_generator_;
@@ -266,12 +467,6 @@
   // 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);
@@ -280,9 +475,8 @@
     mem = tmp.ptr;
     size = tmp.size;
   }
-  SetInitialBlock(mem, size);
+  SerialArena* sa = 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)) {
@@ -298,12 +492,9 @@
 #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;
@@ -316,23 +507,86 @@
     id = lifecycle_id_generator_.id.fetch_add(1, 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
+  return id;
+}
+
+// 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);
+  if (serial == nullptr) {
+    return new (mem) SerialArenaChunk{next_capacity};
+  }
+
+  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);
+  GOOGLE_DCHECK_NE(head, nullptr);
+  // Fast path without acquiring mutex.
+  if (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);
+  }
+  auto* empty_chunk = NewSerialArenaChunk(0, nullptr, nullptr);
+  head_.store(empty_chunk, std::memory_order_relaxed);
+  GOOGLE_DCHECK_EQ(message_owned, IsMessageOwned());
   arena_stats_ = Sample();
 }
 
-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);
+SerialArena* ThreadSafeArena::SetInitialBlock(void* mem, size_t size) {
+  SerialArena* serial = SerialArena::New({mem, size}, *this);
+  AddSerialArena(&thread_cache(), serial);
   CacheSerialArena(serial);
+  return serial;
 }
 
 ThreadSafeArena::~ThreadSafeArena() {
@@ -342,11 +596,6 @@
 
   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.
@@ -356,8 +605,6 @@
   } else {
     GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
   }
-
-  if (collector) collector->OnDestroy(space_allocated);
 }
 
 SerialArena::Memory ThreadSafeArena::Free(size_t* space_allocated) {
@@ -367,6 +614,14 @@
     if (mem.ptr) deallocator(mem);
     mem = a->Free(deallocator);
   });
+  // Free chunks that stored SerialArena.
+  SerialArenaChunk* chunk = head_.load(std::memory_order_relaxed);
+  while (chunk != nullptr) {
+    SerialArenaChunk* next_chunk = chunk->next_chunk();
+    internal::SizedDelete(chunk,
+                          SerialArenaChunk::AllocSize(chunk->capacity()));
+    chunk = next_chunk;
+  }
   return mem;
 }
 
@@ -378,7 +633,6 @@
   // Discard all blocks except the special block (if present).
   size_t space_allocated = 0;
   auto mem = Free(&space_allocated);
-  arena_stats_.RecordReset();
 
   AllocationPolicy* policy = alloc_policy_.get();
   if (policy) {
@@ -390,11 +644,8 @@
       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);
   } else {
-    GOOGLE_DCHECK(!alloc_policy_.should_record_allocs());
     // Nullptr policy
     if (alloc_policy_.is_user_owned_initial_block()) {
       space_allocated += mem.size;
@@ -408,70 +659,92 @@
   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();
   }
-  arena->AddCleanup(elem, cleanup, AllocPolicy());
+  arena->AddCleanup(elem, cleanup, AllocPolicy(), arena_stats_.MutableStats());
 }
 
 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()->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::PerConstSerialArena(Functor fn) const {
+  const SerialArenaChunk* chunk = head_.load(std::memory_order_acquire);
+
+  for (; chunk; chunk = chunk->next_chunk()) {
+    absl::Span<const std::atomic<SerialArena*>> span = chunk->arenas();
+    // Walks arenas backward to handle the first serial arena the last. This is
+    // necessary to special-case the initial block.
+    for (auto it = span.crbegin(); it != span.crend(); ++it) {
+      const SerialArena* serial = it->load(std::memory_order_relaxed);
+      // 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);
     }
   }
-  return GetSerialArenaFallback(&thread_cache())
-      ->AllocateAlignedWithCleanup(n, alloc_policy_.get());
+}
+
+template <typename Functor>
+void ThreadSafeArena::PerSerialArena(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);
+
+  for (; chunk; chunk = chunk->next_chunk()) {
+    absl::Span<std::atomic<SerialArena*>> span = chunk->arenas();
+    // Walks arenas backward to handle the first serial arena the last. This is
+    // necessary to special-case the initial block.
+    for (auto it = span.rbegin(); it != span.rend(); ++it) {
+      SerialArena* serial = it->load(std::memory_order_relaxed);
+      GOOGLE_DCHECK_NE(serial, nullptr);
+      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 = 0;
+  PerConstSerialArena([&space_allocated](const SerialArena* serial) {
+    space_allocated += serial->SpaceAllocated();
+  });
+  return space_allocated;
 }
 
+template <AllocationClient alloc_client>
+PROTOBUF_NOINLINE void* ThreadSafeArena::AllocateAlignedFallback(size_t n) {
+  return GetSerialArenaFallback()->AllocateAligned<alloc_client>(n);
+}
+
+template void* ThreadSafeArena::AllocateAlignedFallback<
+    AllocationClient::kDefault>(size_t);
+template void*
+    ThreadSafeArena::AllocateAlignedFallback<AllocationClient::kArray>(size_t);
+
 uint64_t ThreadSafeArena::SpaceUsed() const {
-  SerialArena* serial = threads_.load(std::memory_order_acquire);
   uint64_t space_used = 0;
-  for (; serial; serial = serial->next()) {
+  PerConstSerialArena([&space_used](const SerialArena* serial) {
     space_used += serial->SpaceUsed();
-  }
+  });
   return space_used - (alloc_policy_.get() ? sizeof(AllocationPolicy) : 0);
 }
 
@@ -480,12 +753,20 @@
 }
 
 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() {
+  void* const id = &thread_cache();
+  SerialArena* serial = nullptr;
+
+  // Search matching SerialArena.
+  SerialArenaChunk* chunk = head_.load(std::memory_order_acquire);
+  for (; chunk; chunk = chunk->next_chunk()) {
+    absl::Span<std::atomic<void*>> ids = chunk->ids();
+    for (unsigned 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;
+      }
     }
   }
 
@@ -493,14 +774,9 @@
     // 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.
     serial = SerialArena::New(
-        AllocateMemory(alloc_policy_.get(), 0, kSerialArenaSize), me,
-        arena_stats_.MutableStats());
+        AllocateMemory(alloc_policy_.get(), 0, 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 +785,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..4bc3994 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>
@@ -131,7 +122,7 @@
   // here.
   size_t max_block_size;
 
-  // 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.
@@ -153,8 +144,8 @@
 
   ArenaOptions()
       : start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize),
-        max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize),
-        initial_block(NULL),
+        max_block_size(internal::GetDefaultArenaMaxBlockSize()),
+        initial_block(nullptr),
         initial_block_size(0),
         block_alloc(nullptr),
         block_dealloc(nullptr),
@@ -176,7 +167,6 @@
     res.max_block_size = max_block_size;
     res.block_alloc = block_alloc;
     res.block_dealloc = block_dealloc;
-    res.metrics_collector = MetricsCollector();
     return res;
   }
 
@@ -186,14 +176,6 @@
   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 +203,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 +213,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.
 //
@@ -274,9 +256,9 @@
   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.
@@ -315,17 +297,26 @@
                              static_cast<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 +335,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 +350,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
@@ -385,8 +379,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 +394,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 +405,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 +486,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 +496,6 @@
       return new T(nullptr);
     }
 
-    static Arena* GetArena(const T* p) { return p->GetArena(); }
-
     friend class Arena;
     friend class TestUtil::ReflectionTester;
   };
@@ -509,8 +511,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 +543,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 +561,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 +576,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 +585,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 +630,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 +639,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)...);
   }
 
@@ -708,9 +690,8 @@
           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)...);
+          new (arena->AllocateInternal(sizeof(T), alignof(T), destructor))
+              T(std::forward<Args>(args)...);
       return result;
     }
   }
@@ -723,8 +704,7 @@
       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)))
+      return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor))
           T(std::forward<Args>(args)...);
     }
   }
@@ -736,13 +716,13 @@
   // using the virtual destructor instead.
   template <typename T>
   PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
-    if (object != NULL) {
+    if (object != nullptr) {
       impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
     }
   }
   template <typename T>
   PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) {
-    if (object != NULL) {
+    if (object != nullptr) {
       impl_.AddCleanup(object, &internal::arena_delete_object<T>);
     }
   }
@@ -750,87 +730,35 @@
   // 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 +768,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/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..813f7d0 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 = 8 << 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..2eb6c50 100644
--- a/src/google/protobuf/arena_impl.h
+++ b/src/google/protobuf/arena_impl.h
@@ -35,20 +35,25 @@
 
 #include <atomic>
 #include <limits>
+#include <string>
 #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/port.h"
+
 
 #ifdef ADDRESS_SANITIZER
 #include <sanitizer/asan_interface.h>
 #endif  // ADDRESS_SANITIZER
 
-#include <google/protobuf/arenaz_sampler.h>
+#include "google/protobuf/arena_config.h"
+#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 +67,148 @@
 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));
+  }
+}
+
+namespace cleanup {
+
+template <typename T>
+void arena_destruct_object(void* object) {
+  reinterpret_cast<T*>(object)->~T();
+}
+
+enum class Tag : uintptr_t {
+  kDynamic = 0,  // {void* elem, void (*destructor)(void*)}
+  kString = 1,   // std::string* | kString
+};
+
+constexpr bool EnableSpecializedTags() {
+  return alignof(std::string) >= 8
+      ;
+}
+
+// All node types must start with a `uintptr_t` that stores `Tag` in its low
+// two bits.
+struct DynamicNode {
+  uintptr_t elem;
+  void (*destructor)(void*);
+};
+
+struct StringNode {
+  uintptr_t elem;
+};
+
+
+inline PROTOBUF_ALWAYS_INLINE void CreateNode(Tag tag, void* pos,
+                                              const void* elem,
+                                              void (*destructor)(void*)) {
+  if (EnableSpecializedTags()) {
+    switch (tag) {
+      case Tag::kString: {
+        StringNode n = {reinterpret_cast<uintptr_t>(elem) |
+                        static_cast<uintptr_t>(Tag::kString)};
+        memcpy(pos, &n, sizeof(n));
+        return;
+      }
+      default:
+        break;
+    }
+  }
+  DynamicNode n = {reinterpret_cast<uintptr_t>(elem), destructor};
+  memcpy(pos, &n, sizeof(n));
+}
+
+inline PROTOBUF_ALWAYS_INLINE void PrefetchNode(const void* elem_address) {
+  (void)elem_address;
+}
+
+inline PROTOBUF_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));
+}
+
+inline PROTOBUF_ALWAYS_INLINE Tag Type(void (*destructor)(void*)) {
+  if (EnableSpecializedTags()) {
+    if (destructor == &arena_destruct_object<std::string>) {
+      return Tag::kString;
+    }
+  }
+  return Tag::kDynamic;
+}
+
+inline PROTOBUF_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;
+  }
+}
+
+inline PROTOBUF_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);
+  }
+}
+
+inline PROTOBUF_ALWAYS_INLINE size_t Size(void (*destructor)(void*)) {
+  return destructor == nullptr ? 0 : Size(Type(destructor));
+}
+
+}  // namespace cleanup
+
 using LifecycleIdAtomic = uint64_t;
 
 // MetricsCollector collects stats for a particular arena.
@@ -104,18 +246,16 @@
 
 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;
+  size_t max_block_size = GetDefaultArenaMaxBlockSize();
   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;
+    return start_block_size == kDefaultStartBlockSize &&
+           max_block_size == GetDefaultArenaMaxBlockSize() &&
+           block_alloc == nullptr && block_dealloc == nullptr;
   }
 };
 
@@ -152,22 +292,11 @@
     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;
@@ -190,6 +319,8 @@
 
 enum class AllocationClient { kDefault, kArray };
 
+class ThreadSafeArena;
+
 // 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 +329,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 +339,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 +346,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,7 +354,7 @@
     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];
@@ -252,9 +376,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 +387,18 @@
     }
 
     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);
+    ASAN_UNPOISON_MEMORY_REGION(ptr(), n);
 #endif  // ADDRESS_SANITIZER
+    void* ret = ptr();
+    set_ptr(static_cast<char*>(ret) + n);
     return ret;
   }
 
@@ -286,13 +410,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 +427,16 @@
 
       std::copy(cached_blocks_, cached_blocks_ + cached_block_length_,
                 new_list);
+
+#ifdef ADDRESS_SANITIZER
+      // We need to unpoison this memory before filling it in case it has been
+      // poisoned by another santizer client.
+      ASAN_UNPOISON_MEMORY_REGION(
+          new_list + cached_block_length_,
+          (new_size - cached_block_length_) * sizeof(CachedBlock*));
+#endif
       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.
@@ -326,54 +459,88 @@
   // 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*),
+                  const AllocationPolicy* policy, ThreadSafeArenaStats* stats) {
+    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;
+  void* AllocateFromExistingWithCleanupFallback(size_t n, size_t align,
+                                                void (*destructor)(void*)) {
+    n = AlignUpTo(n, align);
 #ifdef ADDRESS_SANITIZER
-    ASAN_UNPOISON_MEMORY_REGION(ret, n);
-    ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize);
+    ASAN_UNPOISON_MEMORY_REGION(ptr(), n);
 #endif  // ADDRESS_SANITIZER
-    return CreatePair(ret, reinterpret_cast<CleanupNode*>(limit_));
+    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; }
+#ifdef ADDRESS_SANITIZER
+    ASAN_UNPOISON_MEMORY_REGION(limit_ - n, n);
+#endif  // ADDRESS_SANITIZER
+    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);
@@ -381,34 +548,46 @@
   // 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) {}
+    Block(Block* next, size_t size)
+        : next(next), cleanup_nodes(nullptr), relaxed_size(size) {}
 
     char* Pointer(size_t n) {
-      GOOGLE_DCHECK(n <= size);
+      GOOGLE_DCHECK(n <= size());
       return reinterpret_cast<char*>(this) + n;
     }
 
+    size_t size() const { return relaxed_size.load(std::memory_order_relaxed); }
+
     Block* const next;
-    const size_t size;
-    CleanupNode* start;
+    void* cleanup_nodes;
+
+   private:
+    const std::atomic<size_t> relaxed_size;
     // 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.
+  ThreadSafeArena& parent_;
+  std::atomic<Block*> head_;  // Head of linked list of blocks.
+  std::atomic<size_t> space_used_{0};  // Necessary for metrics.
   std::atomic<size_t> space_allocated_;
 
   // 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_;
+
+  // Helper getters/setters to handle relaxed operations on atomic variables.
+  Block* head() { return head_.load(std::memory_order_relaxed); }
+  const Block* head() const { return head_.load(std::memory_order_relaxed); }
+  void set_head(Block* head) {
+    return head_.store(head, 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); }
+
   // 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_;
 
   // Repeated*Field and Arena play together to reduce memory consumption by
   // reusing blocks. Currently, natural growth of the repeated field types makes
@@ -425,19 +604,15 @@
   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};
-  }
+  inline SerialArena(Block* 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*));
+  void AllocateNewBlock(size_t n);
 
  public:
   static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block));
-  static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode));
 };
 
 // Tag type used to invoke the constructor of message-owned arena.
@@ -469,6 +644,13 @@
     InitializeWithPolicy(mem, size, 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
   // destructors can be skipped. Also, frees all blocks except the initial block
@@ -481,13 +663,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 +686,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,6 +704,21 @@
   }
 
  private:
+  friend class ArenaBenchmark;
+  friend class TcParser;
+  friend class SerialArena;
+  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);
+
+  // Adds SerialArena to the chunked list. May create a new chunk.
+  void AddSerialArena(void* id, SerialArena* serial);
+
   // Unique for each arena. Changes on Reset().
   uint64_t tag_and_id_ = 0;
   // The LSB of tag_and_id_ indicates if the arena is message-owned.
@@ -533,53 +728,32 @@
 
   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
+  // Pointer to a linked list of SerialArenaChunk.
+  std::atomic<SerialArenaChunk*> head_;
+
+  // Adding a new chunk to head_ must be protected by mutex_.
+  absl::Mutex mutex_;
 
   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* AllocateAlignedWithCleanupFallback(size_t n, size_t align,
+                                           void (*destructor)(void*));
 
   void Init();
-  void SetInitialBlock(void* mem, size_t size);
+  SerialArena* 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 +764,22 @@
     }
     return false;
   }
-  SerialArena* GetSerialArenaFallback(void* me);
 
+  // Finds SerialArena or creates one if not found.
+  SerialArena* GetSerialArenaFallback();
+
+  template <AllocationClient alloc_client = AllocationClient::kDefault>
+  void* AllocateAlignedFallback(size_t n);
+
+  // Executes callback function over chunked list of SerialArena in reverse
+  // chronological order. Passes const SerialArena*.
   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 PerConstSerialArena(Functor fn) const;
 
-    for (; serial; serial = serial->next()) fn(serial);
-  }
+  // Executes callback function over chunked list of SerialArena in reverse
+  // chronological order.
+  template <typename Functor>
+  void PerSerialArena(Functor fn);
 
   // 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
@@ -659,12 +839,6 @@
 
   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.
@@ -681,6 +855,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..c576a35 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,29 @@
 #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 "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_arena.pb.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 "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/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;
@@ -84,10 +85,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 +102,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 +118,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 +146,10 @@
         six_(six),
         seven_(seven),
         eight_(eight) {}
+  MustBeConstructedWithOneThroughEight(
+      const MustBeConstructedWithOneThroughEight&) = delete;
+  MustBeConstructedWithOneThroughEight& operator=(
+      const MustBeConstructedWithOneThroughEight&) = delete;
 
   int one_;
   const char* const two_;
@@ -152,9 +159,6 @@
   const char* const six_;
   std::string seven_;
   std::string eight_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughEight);
 };
 
 TEST(ArenaTest, ArenaConstructable) {
@@ -171,17 +175,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 +200,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 +209,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 +218,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 +230,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 +246,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_);
@@ -307,6 +311,26 @@
   }
 }
 
+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()));
+}
+
 TEST(ArenaTest, Parsing) {
   TestAllTypes original;
   TestUtil::SetAllFields(&original);
@@ -484,7 +508,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 +609,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 +627,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 +795,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 +806,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 +1102,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 +1115,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 +1125,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 +1158,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 +1222,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 +1346,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);
@@ -1399,7 +1423,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 +1467,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 +1534,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 +1571,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..2a183d3 100644
--- a/src/google/protobuf/arenastring.cc
+++ b/src/google/protobuf/arenastring.cc
@@ -28,20 +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/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 "google/protobuf/io/coded_stream.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/stubs/stl_util.h"
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
@@ -71,7 +72,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 +88,7 @@
 namespace {
 
 
-#if defined(NDEBUG) || !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL
+#if defined(NDEBUG) || !defined(GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL)
 
 class ScopedCheckPtrInvariants {
  public:
@@ -97,16 +98,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 +117,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 +125,19 @@
     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
   }
 }
 
@@ -264,4 +277,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..519e50d 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"
@@ -259,12 +260,12 @@
   // 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);
   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);
   void SetBytes(const char* s, Arena* arena);
   void SetBytes(const void* p, size_t n, Arena* arena);
@@ -406,14 +407,14 @@
 }
 
 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);
 }
 
@@ -426,7 +427,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 +476,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..efb4bf3 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/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/message_lite.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/strings/string_view.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/compiler/BUILD.bazel b/src/google/protobuf/compiler/BUILD.bazel
new file mode 100644
index 0000000..62e0d39
--- /dev/null
+++ b/src/google/protobuf/compiler/BUILD.bazel
@@ -0,0 +1,354 @@
+################################################################################
+# 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")
+
+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",
+        "@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 = [
+        "//:protobuf",
+        "@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",
+        "//:protobuf",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "protoc_lib",
+    srcs = [
+        "main.cc",
+    ],
+    copts = COPTS,
+    visibility = [
+        "//:__pkg__",
+        "//pkg:__pkg__",
+    ],
+    deps = [
+        ":code_generator",
+        ":command_line_interface",
+        ":importer",
+        "//:protobuf",
+        "//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",
+    ],
+)
+
+# 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/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..76d39ab 100644
--- a/src/google/protobuf/compiler/annotation_test_util.cc
+++ b/src/google/protobuf/compiler/annotation_test_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/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/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 <gtest/gtest.h>
 
 namespace google {
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..6c1a967 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 "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_split.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('=');
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..09d82f0 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -32,11 +32,12 @@
 //  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 "google/protobuf/stubs/platform_macros.h"
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #ifdef major
 #undef major
@@ -58,6 +59,10 @@
 #include <limits.h>  // For PATH_MAX
 
 #include <memory>
+#include <string>
+#include <unordered_set>
+#include <utility>
+#include <vector>
 
 #if defined(__APPLE__)
 #include <mach-o/dyld.h>
@@ -65,29 +70,30 @@
 #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 "google/protobuf/stubs/strutil.h"
+#include "google/protobuf/stubs/stringprintf.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.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"
+#include "google/protobuf/stubs/stl_util.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -174,7 +180,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 +345,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 +407,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;
@@ -815,7 +823,7 @@
 
     // Find the insertion point.
     std::string magic_string =
-        strings::Substitute("@@protoc_insertion_point($0)", insertion_point_);
+        absl::Substitute("@@protoc_insertion_point($0)", insertion_point_);
     std::string::size_type pos = target->find(magic_string);
 
     if (pos == std::string::npos) {
@@ -963,6 +971,7 @@
 
 int CommandLineInterface::Run(int argc, const char* const argv[]) {
   Clear();
+
   switch (ParseArguments(argc, argv)) {
     case PARSE_ARGUMENT_DONE_AND_EXIT:
       return 0;
@@ -1076,7 +1085,6 @@
     }
   }
 
-  // Write all output to disk.
   for (const auto& pair : output_directories) {
     const std::string& location = pair.first;
     GeneratorContextImpl* directory = pair.second.get();
@@ -1151,7 +1159,6 @@
         // Do not add a default case.
     }
   }
-
   return 0;
 }
 
@@ -1276,6 +1283,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 +1303,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;
         }
       }
@@ -1679,8 +1687,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 +1708,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 +1764,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 +1790,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 +1850,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 +1950,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"))) {
       // 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];
@@ -2069,7 +2092,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 +2108,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 +2148,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;
       }
     }
@@ -2296,7 +2322,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 +2349,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);
@@ -2506,6 +2532,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.
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index e842550..6965e1a 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -39,6 +39,7 @@
 #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
 
 #include <cstdint>
+#include <functional>
 #include <map>
 #include <memory>
 #include <set>
@@ -48,10 +49,11 @@
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/common.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 +117,8 @@
   static const char* const kPathSeparator;
 
   CommandLineInterface();
+  CommandLineInterface(const CommandLineInterface&) = delete;
+  CommandLineInterface& operator=(const CommandLineInterface&) = delete;
   ~CommandLineInterface();
 
   // Register a code generator for a language.
@@ -352,7 +356,11 @@
     CodeGenerator* generator;
     std::string help_text;
   };
-  typedef std::map<std::string, GeneratorInfo> GeneratorMap;
+
+  const GeneratorInfo* FindGeneratorByFlag(const std::string& name) const;
+  const GeneratorInfo* FindGeneratorByOption(const std::string& option) const;
+
+  using GeneratorMap = std::map<std::string, GeneratorInfo>;
   GeneratorMap generators_by_flag_name_;
   GeneratorMap generators_by_option_name_;
   // A map from generator names to the parameters specified using the option
@@ -398,7 +406,7 @@
   // 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.
 
@@ -451,14 +459,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..6b330b8 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -45,31 +45,35 @@
 #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/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 <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/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 "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 {
@@ -319,7 +323,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 +353,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 +361,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 +372,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 +410,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 +429,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 +542,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);
 }
 
@@ -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"));
@@ -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,7 +2686,7 @@
 
 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) {
@@ -2690,18 +2695,18 @@
   }
   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") +
           " --decode=protobuf_unittest.TestAllTypes"));
   ExpectStdoutMatchesTextFile(TestUtil::GetTestDataPath(
-      "net/proto2/internal/"
+      "third_party/protobuf/"
       "testdata/text_format_unittest_data_oneof_implemented.txt"));
   ExpectStderrMatchesText("");
 }
@@ -2750,7 +2755,7 @@
 
 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) {
@@ -2760,13 +2765,13 @@
   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") +
           " --decode=protobuf_unittest.TestAllTypes --deterministic_output"));
@@ -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..1798fce
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/BUILD.bazel
@@ -0,0 +1,228 @@
+################################################################################
+# 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 = "cpp",
+    srcs = [
+        "enum.cc",
+        "enum_field.cc",
+        "extension.cc",
+        "field.cc",
+        "file.cc",
+        "generator.cc",
+        "helpers.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",
+        "helpers.h",
+        "map_field.h",
+        "message.h",
+        "message_field.h",
+        "message_layout_helper.h",
+        "names.h",
+        "options.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__",
+    ],
+    deps = [
+        "//:protobuf",
+        "//src/google/protobuf/compiler:code_generator",
+        "@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/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",
+)
+
+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..4685c0a 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 <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/test_util2.h"
+#include "google/protobuf/io/zero_copy_stream_impl.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/stubs/stl_util.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
 namespace {
+std::string FindWithDefault(
+    const absl::flat_hash_map<std::string, 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,
@@ -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<std::string, std::string> vpath_map;
+  absl::flat_hash_map<std::string, 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..b336453 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.h
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.h
@@ -1,6 +1,6 @@
 #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..2cd152a 100644
--- a/src/google/protobuf/compiler/cpp/enum.cc
+++ b/src/google/protobuf/compiler/cpp/enum.cc
@@ -32,16 +32,18 @@
 //  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 <cstdint>
 #include <limits>
 #include <map>
+#include <unordered_set>
+#include <utility>
 
-#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/io/printer.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/names.h"
 
 namespace google {
 namespace protobuf {
@@ -49,9 +51,9 @@
 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.
+// 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++) {
@@ -65,13 +67,44 @@
 // 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;
+  std::unordered_set<int> values;
   for (int i = 0; i < descriptor->value_count(); ++i) {
     values.insert(descriptor->value(i)->number());
   }
   return values.size();
 }
 
+struct MinMaxEnumDescriptors {
+  const EnumValueDescriptor* min;
+  const EnumValueDescriptor* max;
+};
+MinMaxEnumDescriptors EnumLimits(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 {min_desc, max_desc};
+}
+
+// Assumes that HasDescriptorMethods is true.
+bool ShouldCacheDenseEnum(const EnumDescriptor* descriptor,
+                          MinMaxEnumDescriptors limits) {
+  // The conditions here for what is "sparse" are not rigorously
+  // chosen.  We use unsigned values in case the subtraction of min from max
+  // exceeds the bounds of int.
+  const unsigned values_range = static_cast<unsigned>(limits.max->number()) -
+                                static_cast<unsigned>(limits.min->number());
+  return (values_range < 16u ||
+          values_range < static_cast<unsigned>(descriptor->value_count()) * 2u);
+}
+
 }  // namespace
 
 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
@@ -98,9 +131,6 @@
   format("enum ${1$$classname$$}$ : int {\n", descriptor_);
   format.Indent();
 
-  const EnumValueDescriptor* min_value = descriptor_->value(0);
-  const EnumValueDescriptor* max_value = descriptor_->value(0);
-
   for (int i = 0; i < descriptor_->value_count(); i++) {
     auto format_value = format;
     format_value.Set("name", EnumValueName(descriptor_->value(i)));
@@ -114,13 +144,6 @@
     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) {
@@ -137,13 +160,15 @@
   format.Outdent();
   format("\n};\n");
 
+  MinMaxEnumDescriptors enum_limits = EnumLimits(descriptor_);
   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));
+      descriptor_, EnumValueName(enum_limits.min),
+      EnumValueName(enum_limits.max));
 
   if (generate_array_size_) {
     format(
@@ -172,9 +197,19 @@
       "    ::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 (ShouldCacheDenseEnum(descriptor_, enum_limits)) {
+      // 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.
+      format(
+          "  return "
+          "$classname$_Name(static_cast<$classname$>(enum_t_value));\n");
+    } else {
+      format(
+          "  return ::$proto_ns$::internal::NameOfEnum(\n"
+          "    $classname$_descriptor(), enum_t_value);\n");
+    }
   } else {
     format(
         "  return $classname$_Name(static_cast<$classname$>(enum_t_value));\n");
@@ -182,9 +217,18 @@
   format("}\n");
 
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    if (ShouldCacheDenseEnum(descriptor_, enum_limits)) {
+      format(
+          "template<>\n"
+          "inline const std::string& $classname$_Name($classname$ value) {\n"
+          "  return ::$proto_ns$::internal::NameOfDenseEnum\n"
+          "    <$classname$_descriptor, $1$, $2$>(static_cast<int>(value));\n"
+          "}\n",
+          enum_limits.min->number(), enum_limits.max->number());
+    }
     format(
         "inline bool $classname$_Parse(\n"
-        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+        "    ::absl::string_view name, $classname$* "
         "value) "
         "{\n"
         "  return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n"
@@ -193,7 +237,7 @@
   } else {
     format(
         "bool $classname$_Parse(\n"
-        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+        "    ::absl::string_view name, $classname$* "
         "value);\n");
   }
 }
@@ -261,7 +305,7 @@
       "}\n");
   format(
       "static inline bool "
-      "$nested_name$_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,\n"
+      "$nested_name$_Parse(::absl::string_view name,\n"
       "    $resolved_name$* value) {\n"
       "  return $classname$_Parse(name, value);\n"
       "}\n");
@@ -391,7 +435,7 @@
         CountUniqueValues(descriptor_));
     format(
         "bool $classname$_Parse(\n"
-        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
+        "    ::absl::string_view name, $classname$* "
         "value) "
         "{\n"
         "  int int_value;\n"
diff --git a/src/google/protobuf/compiler/cpp/enum.h b/src/google/protobuf/compiler/cpp/enum.h
index 610d4fc..33ec310 100644
--- a/src/google/protobuf/compiler/cpp/enum.h
+++ b/src/google/protobuf/compiler/cpp/enum.h
@@ -39,8 +39,8 @@
 #include <set>
 #include <string>
 
-#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 {
@@ -61,6 +61,8 @@
   EnumGenerator(const EnumDescriptor* descriptor,
                 const std::map<std::string, std::string>& vars,
                 const Options& options);
+  EnumGenerator(const EnumGenerator&) = delete;
+  EnumGenerator& operator=(const EnumGenerator&) = delete;
   ~EnumGenerator();
 
   // Generate header code defining the enum.  This code should be placed
@@ -95,7 +97,6 @@
   std::map<std::string, std::string> variables_;
 
   friend class FileGenerator;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/enum_field.cc b/src/google/protobuf/compiler/cpp/enum_field.cc
index 8ffb699..2a0397f 100644
--- a/src/google/protobuf/compiler/cpp/enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/enum_field.cc
@@ -32,13 +32,13 @@
 //  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 "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"
 
 namespace google {
 namespace protobuf {
@@ -104,7 +104,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(
@@ -204,7 +204,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(
@@ -252,7 +252,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 +291,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 +300,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 +366,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"
@@ -402,8 +404,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..e5d476c 100644
--- a/src/google/protobuf/compiler/cpp/enum_field.h
+++ b/src/google/protobuf/compiler/cpp/enum_field.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/cpp/field.h>
+#include "google/protobuf/compiler/cpp/field.h"
 
 namespace google {
 namespace protobuf {
@@ -48,6 +48,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 +68,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 +83,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 +90,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 +113,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..4166b08 100644
--- a/src/google/protobuf/compiler/cpp/extension.cc
+++ b/src/google/protobuf/compiler/cpp/extension.cc
@@ -32,14 +32,16 @@
 //  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 "google/protobuf/io/printer.h"
+#include "google/protobuf/stubs/strutil.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"
 
 namespace google {
 namespace protobuf {
@@ -77,7 +79,6 @@
       type_traits_.append(" >");
       break;
   }
-  SetCommonVars(options, &variables_);
   SetCommonMessageDataVariables(descriptor_->containing_type(), &variables_);
   variables_["extendee"] =
       QualifiedClassName(descriptor_->containing_type(), options_);
@@ -86,14 +87,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 +105,7 @@
 
   variables_["verify_fn"] =
       add_verify_fn
-          ? StrCat("&", FieldMessageTypeName(descriptor_, options_),
+          ? absl::StrCat("&", FieldMessageTypeName(descriptor_, options_),
                          "::InternalVerify")
           : "nullptr";
 }
@@ -159,7 +160,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..1c0e020 100644
--- a/src/google/protobuf/compiler/cpp/extension.h
+++ b/src/google/protobuf/compiler/cpp/extension.h
@@ -38,8 +38,8 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/cpp/options.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.
@@ -83,8 +85,6 @@
   MessageSCCAnalyzer* scc_analyzer_;
 
   std::map<std::string, std::string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/field.cc b/src/google/protobuf/compiler/cpp/field.cc
index 90d2084..bc93afa 100644
--- a/src/google/protobuf/compiler/cpp/field.cc
+++ b/src/google/protobuf/compiler/cpp/field.cc
@@ -32,25 +32,27 @@
 //  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 "absl/strings/str_cat.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/io/printer.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/stubs/strutil.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"
 
 namespace google {
 namespace protobuf {
@@ -62,22 +64,22 @@
 namespace {
 
 void MaySetAnnotationVariable(const Options& options,
-                              StringPiece annotation_name,
-                              StringPiece substitute_template_prefix,
-                              StringPiece prepared_template,
-                              int field_index, StringPiece access_type,
+                              absl::string_view annotation_name,
+                              absl::string_view substitute_template_prefix,
+                              absl::string_view prepared_template,
+                              int field_index, absl::string_view access_type,
                               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(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
@@ -85,13 +87,13 @@
           : "$0";
 
   if (descriptor->default_value_string().empty()) {
-    return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ",
+    return absl::Substitute(absl::StrCat("_internal_has_", field_name, "() ? ",
                                          field_pointer, ": nullptr"),
                             field_member);
   }
 
   if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING_PIECE) {
-    return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ",
+    return absl::Substitute(absl::StrCat("_internal_has_", field_name, "() ? ",
                                          field_pointer, ": nullptr"),
                             field_member);
   }
@@ -100,25 +102,25 @@
       descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
           ? "&$1.get()"
           : "&$1";
-  return strings::Substitute(
-      StrCat("_internal_has_", field_name, "() ? ", field_pointer, " : ",
+  return absl::Substitute(
+      absl::StrCat("_internal_has_", field_name, "() ? ", 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
@@ -134,12 +136,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 +155,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 +167,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 +182,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;
   }
@@ -235,19 +236,18 @@
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
                              std::map<std::string, std::string>* variables,
                              const Options& options) {
-  SetCommonVars(options, variables);
   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)["index"] = absl::StrCat(descriptor->index());
+  (*variables)["number"] = absl::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);
 
-  (*variables)["tag_size"] = StrCat(
+  (*variables)["tag_size"] = absl::StrCat(
       WireFormat::TagSize(descriptor->number(), descriptor->type()));
   (*variables)["deprecated_attr"] = DeprecatedAttribute(options, descriptor);
 
@@ -267,16 +267,16 @@
 }
 
 void FieldGenerator::SetHasBitIndex(int32_t has_bit_index) {
-  if (!HasHasbit(descriptor_)) {
+  if (!internal::cpp::HasHasbit(descriptor_)) {
     GOOGLE_CHECK_EQ(has_bit_index, -1);
     return;
   }
-  variables_["set_hasbit"] = StrCat(
+  variables_["set_hasbit"] = absl::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(
+      absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8), "u;");
+  variables_["clear_hasbit"] = absl::StrCat(
       variables_["has_bits"], "[", has_bit_index / 32, "] &= ~0x",
-      strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
+      absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8), "u;");
 }
 
 void FieldGenerator::SetInlinedStringIndex(int32_t inlined_string_index) {
@@ -287,16 +287,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");
 }
 
diff --git a/src/google/protobuf/compiler/cpp/field.h b/src/google/protobuf/compiler/cpp/field.h
index dd2a51a..b23a2a6 100644
--- a/src/google/protobuf/compiler/cpp/field.h
+++ b/src/google/protobuf/compiler/cpp/field.h
@@ -40,9 +40,9 @@
 #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 "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/options.h"
 
 namespace google {
 namespace protobuf {
@@ -74,6 +74,8 @@
   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 +152,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.
@@ -222,9 +221,6 @@
   const FieldDescriptor* descriptor_;
   const Options& options_;
   std::map<std::string, std::string> variables_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
 };
 
 // Convenience class which constructs FieldGenerators for a Descriptor.
@@ -232,6 +228,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 +256,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..dff09a8 100644
--- a/src/google/protobuf/compiler/cpp/file.cc
+++ b/src/google/protobuf/compiler/cpp/file.cc
@@ -32,7 +32,7 @@
 //  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>
@@ -42,19 +42,20 @@
 #include <unordered_set>
 #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/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_replace.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/service.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -109,7 +110,6 @@
 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"] =
@@ -171,7 +171,7 @@
   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) {
+    for (int j = 0; j < ABSL_ARRAYSIZE(kMacroNames); ++j) {
       if (name == kMacroNames[j]) {
         names_to_undef.push_back(name);
         break;
@@ -257,7 +257,8 @@
     return;
   }
 
-  GenerateTopHeaderGuard(printer, false);
+  GenerateTopHeaderGuard(printer,
+                         google::protobuf::compiler::cpp::GeneratedFileType::kProtoH);
 
   if (!options_.opensource_runtime) {
     format(
@@ -285,13 +286,15 @@
 
   GenerateHeader(printer);
 
-  GenerateBottomHeaderGuard(printer, false);
+  GenerateBottomHeaderGuard(printer,
+                            google::protobuf::compiler::cpp::GeneratedFileType::kProtoH);
 }
 
 void FileGenerator::GeneratePBHeader(io::Printer* printer,
                                      const std::string& info_path) {
   Formatter format(printer, variables_);
-  GenerateTopHeaderGuard(printer, true);
+  GenerateTopHeaderGuard(printer,
+                         google::protobuf::compiler::cpp::GeneratedFileType::kPbH);
 
   if (options_.proto_h) {
     std::string target_basename = StripProto(file_->name());
@@ -330,7 +333,8 @@
         "\n");
   }
 
-  GenerateBottomHeaderGuard(printer, true);
+  GenerateBottomHeaderGuard(printer,
+                            google::protobuf::compiler::cpp::GeneratedFileType::kPbH);
 }
 
 void FileGenerator::DoIncludeFile(const std::string& google3_name,
@@ -346,7 +350,7 @@
     path = StringReplace(path, "proto/", "", false);
     path = StringReplace(path, "public/", "", false);
     if (options_.runtime_include_base.empty()) {
-      format("#include <google/protobuf/$1$>", path);
+      format("#include \"google/protobuf/$1$\"", path);
     } else {
       format("#include \"$1$google/protobuf/$2$\"",
              options_.runtime_include_base, path);
@@ -495,20 +499,18 @@
     generator->GenerateInitDefaultSplitInstance(printer);
     format(
         "} {}\n"
-        "  ~$1$() {}\n"
         "  union {\n"
-        "    $2$ _instance;\n"
+        "    $1$ _instance;\n"
         "  };\n"
         "};\n",
-        DefaultInstanceType(generator->descriptor_, options_, /*split=*/true),
-        StrCat(generator->classname_, "::Impl_::Split"));
+        absl::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",
+        "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const $1$ $2$;\n",
         DefaultInstanceType(generator->descriptor_, options_, /*split=*/true),
         DefaultInstanceName(generator->descriptor_, options_, /*split=*/true));
   }
@@ -880,7 +882,7 @@
       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("'$1$', ", absl::CEscape(file_data.substr(i, 1)));
         }
         format("\n");
       }
@@ -891,7 +893,7 @@
       for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
         format(
             "\"$1$\"\n",
-            EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
+            EscapeTrigraphs(absl::CEscape(file_data.substr(i, kBytesPerLine))));
       }
     }
     format(";\n");
@@ -926,7 +928,7 @@
   // so disable for now.
   bool eager = false;
   format(
-      "static ::_pbi::once_flag $desc_table$_once;\n"
+      "static ::absl::once_flag $desc_table$_once;\n"
       "const ::_pbi::DescriptorTable $desc_table$ = {\n"
       "    false, $1$, $2$, $3$,\n"
       "    \"$filename$\",\n"
@@ -999,7 +1001,7 @@
       const Descriptor* class_desc = p.second;
       format(
           "struct $1$;\n"
-          "$dllexport_decl $extern $1$ $2$;\n",
+          "$dllexport_decl $extern const $1$ $2$;\n",
           DefaultInstanceType(class_desc, options, /*split=*/true),
           DefaultInstanceName(class_desc, options, /*split=*/true));
     }
@@ -1085,7 +1087,8 @@
   format("PROTOBUF_NAMESPACE_CLOSE\n");
 }
 
-void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, bool pb_h) {
+void FileGenerator::GenerateTopHeaderGuard(
+    io::Printer* printer, google::protobuf::compiler::cpp::GeneratedFileType file_type) {
   Formatter format(printer, variables_);
   // Generate top of header.
   format(
@@ -1097,7 +1100,7 @@
       "\n"
       "#include <limits>\n"
       "#include <string>\n",
-      IncludeGuard(file_, pb_h, options_));
+      IncludeGuard(file_, file_type, 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");
@@ -1105,10 +1108,11 @@
   format("\n");
 }
 
-void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h) {
+void FileGenerator::GenerateBottomHeaderGuard(
+    io::Printer* printer, google::protobuf::compiler::cpp::GeneratedFileType file_type) {
   Formatter format(printer, variables_);
   format("#endif  // $GOOGLE_PROTOBUF$_INCLUDED_$1$\n",
-         IncludeGuard(file_, pb_h, options_));
+         IncludeGuard(file_, file_type, options_));
 }
 
 void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/cpp/file.h b/src/google/protobuf/compiler/cpp/file.h
index ca05361..072b913 100644
--- a/src/google/protobuf/compiler/cpp/file.h
+++ b/src/google/protobuf/compiler/cpp/file.h
@@ -41,11 +41,12 @@
 #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/cpp/field.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/compiler/scc.h"
+#include "google/protobuf/compiler/cpp/options.h"
 
 namespace google {
 namespace protobuf {
@@ -70,6 +71,8 @@
  public:
   // See generator.cc for the meaning of dllexport_decl.
   FileGenerator(const FileDescriptor* file, const Options& options);
+  FileGenerator(const FileGenerator&) = delete;
+  FileGenerator& operator=(const FileGenerator&) = delete;
   ~FileGenerator();
 
   // Shared code between the two header generators below.
@@ -134,8 +137,10 @@
   void GenerateForwardDeclarations(io::Printer* printer);
 
   // 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* printer, google::protobuf::compiler::cpp::GeneratedFileType file_type);
+  void GenerateBottomHeaderGuard(
+      io::Printer* printer, google::protobuf::compiler::cpp::GeneratedFileType file_type);
 
   // Generates #include directives.
   void GenerateLibraryIncludes(io::Printer* printer);
@@ -197,8 +202,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..3c25ec8 100644
--- a/src/google/protobuf/compiler/cpp/generator.cc
+++ b/src/google/protobuf/compiler/cpp/generator.cc
@@ -32,31 +32,61 @@
 //  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 <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 "google/protobuf/stubs/strutil.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_replace.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<std::string, 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"},
+
+      // 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"
+                     : "CHECK"},
+      {"DCHK", is_oss ? "GOOGLE_DCHECK"
+                      : "DCHECK"},
+  };
 }
 }  // namespace
 
@@ -64,7 +94,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 +123,70 @@
   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 = strto32(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 == "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));
+              .insert(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;
     }
   }
@@ -183,39 +213,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 +267,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 +288,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..bba2ff5 100644
--- a/src/google/protobuf/compiler/cpp/helpers.cc
+++ b/src/google/protobuf/compiler/cpp/helpers.cc
@@ -32,35 +32,45 @@
 //  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 <set>
+#include <string>
 #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/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/descriptor.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 "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/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"
+
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -72,11 +82,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,48 +170,43 @@
     "wchar_t",
     "while",
     "xor",
-    "xor_eq"};
+    "xor_eq",
+#ifdef PROTOBUF_FUTURE_CPP20_KEYWORDS  // C++20 keywords.
+    "char8_t",
+    "char16_t",
+    "char32_t",
+    "concept",
+    "consteval",
+    "constinit",
+    "co_await",
+    "co_return",
+    "co_yield",
+    "requires",
+#endif  // !PROTOBUF_FUTURE_BREAKING_CHANGES
+};
 
-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<std::string>& Keywords() {
+  static const auto* keywords = [] {
+    auto* keywords = new absl::flat_hash_set<std::string>();
+
+    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);
-}
-
 // Returns true if the message can potentially allocate memory for its field.
 // This is used to determine if message-owned arena will be useful.
 bool AllocExpected(const Descriptor* descriptor) {
   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,43 +234,6 @@
   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";
-}
-
 void SetCommonMessageDataVariables(
     const Descriptor* descriptor,
     std::map<std::string, std::string>* variables) {
@@ -399,7 +368,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());
 }
 
@@ -494,7 +463,7 @@
 }
 
 std::string ResolveKeyword(const std::string& name) {
-  if (kKeywords.count(name) > 0) {
+  if (Keywords().count(name) > 0) {
     return name + "_";
   }
   return name;
@@ -502,23 +471,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 +501,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 +546,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;
@@ -713,9 +682,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 +692,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 +710,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:
@@ -782,12 +751,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 +773,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 +795,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 +811,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 +825,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 +875,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 +1020,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 +1070,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 +1084,7 @@
       "google/protobuf/type.proto",
       "google/protobuf/wrappers.proto",
   };
-  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;
-  }
+  return well_known_files->find(file->name()) != well_known_files->end();
 }
 
 static void GenerateUtf8CheckCode(const FieldDescriptor* field,
@@ -1139,8 +1093,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 +1116,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 +1129,7 @@
       format.Outdent();
       break;
     }
-    case Utf8CheckMode::kNone:
+    case internal::cpp::Utf8CheckMode::kNone:
       break;
   }
 }
@@ -1343,16 +1299,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<std::string, 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 +1336,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 +1441,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 +1488,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..19120e3 100644
--- a/src/google/protobuf/compiler/cpp/helpers.h
+++ b/src/google/protobuf/compiler/cpp/helpers.h
@@ -41,18 +41,21 @@
 #include <map>
 #include <string>
 
-#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 "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_split.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 "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 {
@@ -84,9 +87,6 @@
 extern const char kThickSeparator[];
 extern const char kThinSeparator[];
 
-void SetCommonVars(const Options& options,
-                   std::map<std::string, std::string>* variables);
-
 // Variables to access message data from the message scope.
 void SetCommonMessageDataVariables(
     const Descriptor* descriptor,
@@ -220,7 +220,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 +296,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 +327,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
@@ -377,6 +379,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 +462,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 +483,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 +503,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 +516,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
@@ -850,9 +849,9 @@
   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(absl::Hex x) { return absl::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); }
@@ -898,7 +897,7 @@
 
   void ChangeTo(const std::string& name) {
     std::vector<std::string> new_stack_ =
-        Split(name, "::", true);
+        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) {
@@ -928,15 +927,6 @@
   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 +937,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 +1012,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..ab8501d 100644
--- a/src/google/protobuf/compiler/cpp/map_field.cc
+++ b/src/google/protobuf/compiler/cpp/map_field.cc
@@ -28,24 +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/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 "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "google/protobuf/compiler/cpp/helpers.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) {
@@ -67,12 +62,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..06f3e0a 100644
--- a/src/google/protobuf/compiler/cpp/map_field.h
+++ b/src/google/protobuf/compiler/cpp/map_field.h
@@ -34,8 +34,8 @@
 #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 +46,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 +73,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..e779bc6 100644
--- a/src/google/protobuf/compiler/cpp/message.cc
+++ b/src/google/protobuf/compiler/cpp/message.cc
@@ -32,39 +32,44 @@
 //  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 <cstdint>
 #include <functional>
+#include <limits>
 #include <map>
 #include <memory>
+#include <type_traits>
 #include <unordered_map>
 #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/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 "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/stubs/stringprintf.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/padding_optimizer.h"
+#include "google/protobuf/compiler/cpp/parse_function_generator.h"
+#include "google/protobuf/descriptor.pb.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -73,6 +78,8 @@
 
 using internal::WireFormat;
 using internal::WireFormatLite;
+using internal::cpp::HasHasbit;
+using internal::cpp::Utf8CheckMode;
 
 namespace {
 
@@ -84,21 +91,21 @@
 // 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");
 }
 
@@ -112,7 +119,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));
@@ -290,9 +297,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()));
+      "TYPE_" + absl::AsciiStrToUpper(DeclaredTypeMethodName(val->type()));
 }
 
 // Does the given field have a private (internal helper only) has_$name$()
@@ -303,14 +310,6 @@
   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;
-}
-
 
 // Returns true to make the message serialize in order, decided by the following
 // factors in the order of precedence.
@@ -411,7 +410,6 @@
         has_bit_indices_(has_bit_indices),
         access_info_map_(options.access_info_map),
         cold_threshold_(cold_threshold) {
-    SetCommonVars(options, &variables_);
     SetCommonMessageDataVariables(descriptor, &variables_);
   }
 
@@ -492,7 +490,7 @@
     if (this_word != first_word) {
       format(" ||\n    ");
     }
-    format.Set("mask", strings::Hex(mask, strings::ZERO_PAD_8));
+    format.Set("mask", absl::Hex(mask, absl::kZeroPad8));
     if (this_word == cached_has_word_index) {
       format("(cached_has_bits & 0x$mask$u) != 0");
     } else {
@@ -514,15 +512,15 @@
 }
 
 void MaySetAnnotationVariable(const Options& options,
-                              StringPiece annotation_name,
-                              StringPiece injector_template_prefix,
-                              StringPiece injector_template_suffix,
+                              absl::string_view annotation_name,
+                              absl::string_view injector_template_prefix,
+                              absl::string_view 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)[absl::StrCat("annotate_", annotation_name)] = absl::Substitute(
+      absl::StrCat(injector_template_prefix, injector_template_suffix),
       (*variables)["classtype"]);
 }
 
@@ -551,8 +549,8 @@
   if (!HasTracker(descriptor, options)) {
     return;
   }
-  StringPiece tracker = (*variables)["tracker"];
-  StringPiece extensions = (*variables)["extensions"];
+  absl::string_view tracker = (*variables)["tracker"];
+  absl::string_view 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;
@@ -561,7 +559,7 @@
         !StrContains(annotation_name, "clear")) {
       // Primitive fields accessors.
       // "Has" is here as users calling "has" on a repeated field is a mistake.
-      (*variables)[annotation_name] = StrCat(
+      (*variables)[annotation_name] = absl::StrCat(
           "  ", tracker, ".", listener_call,
           "(this, id.number(), _proto_TypeTraits::GetPtr(id.number(), ",
           extensions, ", id.default_value_ref()));");
@@ -571,17 +569,17 @@
       // Repeated index accessors.
       std::string str_index = "index";
       if (StrContains(annotation_name, "add")) {
-        str_index = StrCat(extensions, ".ExtensionSize(id.number()) - 1");
+        str_index = absl::StrCat(extensions, ".ExtensionSize(id.number()) - 1");
       }
       (*variables)[annotation_name] =
-          StrCat("  ", tracker, ".", listener_call,
+          absl::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(
+      (*variables)[annotation_name] = absl::StrCat(
           "  ", tracker, ".", listener_call,
           "(this, id.number(), _proto_TypeTraits::GetRepeatedPtr(id.number(), ",
           extensions, "));");
@@ -631,7 +629,7 @@
 
   if (HasTracker(descriptor_, options_)) {
     const std::string injector_template =
-        StrCat("  ", variables_["tracker"], ".");
+        absl::StrCat("  ", variables_["tracker"], ".");
 
     MaySetAnnotationVariable(options, "serialize", injector_template,
                              "OnSerialize(this);\n", &variables_);
@@ -790,42 +788,44 @@
 
     std::map<std::string, std::string> vars;
     SetCommonFieldVariables(field, &vars, options_);
+
     format.AddMap(vars);
 
-    if (field->is_repeated()) {
-      format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field,
-             !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
-      if (!IsFieldStripped(field, options_)) {
+      if (field->is_repeated()) {
         format(
-            "private:\n"
-            "int ${1$_internal_$name$_size$}$() const;\n"
-            "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_)) {
+            "$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field,
+            !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
+        if (!IsFieldStripped(field, options_)) {
+          format(
+              "private:\n"
+              "int ${1$_internal_$name$_size$}$() const;\n"
+              "public:\n",
+              field);
+        }
+      } 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();}");
+        if (!IsFieldStripped(field, options_)) {
+          format(
+              "private:\n"
+              "bool _internal_has_$name$() const;\n"
+              "public:\n");
+        }
+      } else if (HasPrivateHasMethod(field)) {
+        if (!IsFieldStripped(field, options_)) {
+          format(
+              "private:\n"
+              "bool ${1$_internal_has_$name$$}$() const;\n"
+              "public:\n",
+              field);
+        }
       }
-    } else if (HasPrivateHasMethod(field)) {
-      if (!IsFieldStripped(field, options_)) {
-        format(
-            "private:\n"
-            "bool ${1$_internal_has_$name$$}$() const;\n"
-            "public:\n",
-            field);
-      }
-    }
-    format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field,
-           !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}");
+      format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field,
+             !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}");
 
     // Generate type-specific accessor declarations.
     field_generators_.get(field).GenerateAccessorDeclarations(printer);
-
     format("\n");
   }
 
@@ -1073,7 +1073,7 @@
 
     format.Set("has_array_index", has_bit_index / 32);
     format.Set("has_mask",
-               strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+               absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8));
     format(
         "inline bool $classname$::_internal_has_$name$() const {\n"
         "  bool value = "
@@ -1121,7 +1121,7 @@
   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()));
+    format.Set("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"
@@ -1210,7 +1210,7 @@
       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));
+                 absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8));
       format("$has_bits$[$has_array_index$] &= ~0x$has_mask$u;\n");
     }
   }
@@ -1260,17 +1260,16 @@
       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()));
+                 absl::StrCat(field->containing_oneof()->index()));
       GenerateOneofMemberHasBits(field, format);
     } else {
       // Singular field.
       GenerateSingularFieldHasBits(field, format);
     }
 
-    if (!IsCrossFileMaybeMap(field)) {
-      GenerateFieldClear(field, true, format);
-    }
-
+      if (!IsCrossFileMaybeMap(field)) {
+        GenerateFieldClear(field, true, format);
+      }
     // Generate type-specific accessors.
     if (!IsFieldStripped(field, options_)) {
       field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
@@ -1285,8 +1284,6 @@
 
 void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
   Formatter format(printer, variables_);
-  format.Set("class_final",
-             ShouldMarkClassAsFinal(descriptor_, options_) ? "final" : "");
 
   if (IsMapEntryMessage(descriptor_)) {
     std::map<std::string, std::string> vars;
@@ -1314,7 +1311,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 +1385,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 +1488,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 +1517,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 +1539,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 +1557,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 +1570,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");
   }
 
@@ -1693,11 +1688,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 +1751,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",
@@ -1852,7 +1845,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(
@@ -1926,6 +1919,8 @@
         "  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");
   }
 
@@ -1986,9 +1981,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));
   }
@@ -2036,7 +2028,6 @@
     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);
 }
@@ -2087,7 +2078,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,7 +2092,14 @@
   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);
@@ -2197,9 +2195,14 @@
     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);
@@ -2274,7 +2277,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 +2314,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 +2345,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 +2354,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);
     }
@@ -2398,8 +2415,15 @@
   }
   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();
@@ -2460,6 +2484,13 @@
     field_generators_.get(field).GenerateConstructorCode(printer);
   }
 
+  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_)) {
     format("clear_has_$1$();\n", oneof->name());
   }
@@ -2468,45 +2499,6 @@
   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) {
   if (!ShouldSplit(descriptor_, options_)) return;
 
@@ -2690,7 +2682,7 @@
   }
   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));
   }
 
@@ -2738,17 +2730,11 @@
       "  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) {
@@ -2779,6 +2765,20 @@
       field_generators_.get(field).GenerateCopyConstructorCode(printer);
     }
   }
+
+  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(printer);
+      }
+    }
+    format.Outdent();
+    format("}\n");
+  }
 }
 
 void MessageGenerator::GenerateStructors(io::Printer* printer) {
@@ -2867,8 +2867,10 @@
       }
       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();
@@ -2930,7 +2932,7 @@
           "case $1$_NOT_SET: {\n"
           "  break;\n"
           "}\n",
-          ToUpper(oneof->name()));
+          absl::AsciiStrToUpper(oneof->name()));
       format.Outdent();
       format("}\n");
     }
@@ -2945,10 +2947,6 @@
   // Generate the shared constructor code.
   GenerateSharedConstructorCode(printer);
 
-  if (ShouldSplit(descriptor_, options_)) {
-    GenerateCreateSplitMessage(printer);
-  }
-
   // Generate the destructor.
   if (!HasSimpleBaseClass(descriptor_, options_)) {
     format(
@@ -3057,15 +3055,26 @@
   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);
 
     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)) {
         GOOGLE_CHECK(!saw_non_zero_init);
@@ -3089,7 +3098,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,25 +3114,20 @@
       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);
       } 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"
             "    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));
       }
     }
 
@@ -3152,14 +3156,16 @@
       }
     }
 
-    if (chunk_is_cold) {
+    if (have_outer_if) {
       format.Outdent();
       format("}\n");
     }
 
-    if (have_outer_if) {
-      format.Outdent();
-      format("}\n");
+    if (chunk_index == chunks.size() - 1) {
+      if (first_split_chunk_processed) {
+        format.Outdent();
+        format("}\n");
+      }
     }
 
     if (cold_skipper.OnEndChunk(chunk_index, printer)) {
@@ -3223,12 +3229,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"
@@ -3452,7 +3458,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
@@ -3500,8 +3506,8 @@
         // 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();
 
@@ -3555,7 +3561,7 @@
         "case $1$_NOT_SET: {\n"
         "  break;\n"
         "}\n",
-        ToUpper(oneof->name()));
+        absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format("}\n");
   }
@@ -3690,7 +3696,7 @@
     int has_bit_index = HasBitIndex(field);
     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));
+          absl::StrCat(absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8));
 
       format("if (cached_has_bits & 0x$1$u) {\n", mask);
     } else {
@@ -3715,8 +3721,8 @@
 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);
+  vars["start"] = absl::StrCat(range->start);
+  vars["end"] = absl::StrCat(range->end);
   Formatter format(printer, vars);
   format("// Extension range [$start$, $end$)\n");
   format(
@@ -4245,7 +4251,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
@@ -4328,7 +4334,7 @@
         "case $1$_NOT_SET: {\n"
         "  break;\n"
         "}\n",
-        ToUpper(oneof->name()));
+        absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format("}\n");
   }
@@ -4427,7 +4433,7 @@
         "case $1$_NOT_SET: {\n"
         "  break;\n"
         "}\n",
-        ToUpper(oneof->name()));
+        absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format("}\n");
   }
@@ -4443,4 +4449,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..3b087d3 100644
--- a/src/google/protobuf/compiler/cpp/message.h
+++ b/src/google/protobuf/compiler/cpp/message.h
@@ -36,15 +36,16 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
 
 #include <cstdint>
+#include <limits>
 #include <memory>
 #include <set>
 #include <string>
 
-#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/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 {
@@ -69,6 +70,8 @@
                    const std::map<std::string, std::string>& vars,
                    int index_in_file_messages, const Options& options,
                    MessageSCCAnalyzer* scc_analyzer);
+  MessageGenerator(const MessageGenerator&) = delete;
+  MessageGenerator& operator=(const MessageGenerator&) = delete;
   ~MessageGenerator();
 
   // Append the two types of nested generators to the corresponding vector.
@@ -119,7 +122,6 @@
   // default instance.
   void GenerateConstexprConstructor(io::Printer* printer);
 
-  void GenerateCreateSplitMessage(io::Printer* printer);
   void GenerateInitDefaultSplitInstance(io::Printer* printer);
 
   // Generate standard Message methods.
@@ -221,7 +223,6 @@
   std::map<std::string, 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..74cca18 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/io/printer.h"
+#include "google/protobuf/compiler/cpp/field.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
 
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/strutil.h"
 
 namespace google {
 namespace protobuf {
@@ -73,7 +73,7 @@
       QualifiedDefaultInstancePtr(descriptor->message_type(), options),
       implicit_weak);
   (*variables)["type_reference_function"] =
-      implicit_weak ? ("  ::" + (*variables)["proto_ns"] +
+      implicit_weak ? ("  ::" + ProtobufNamespace(options) +
                        "::internal::StrongReference(reinterpret_cast<const " +
                        (*variables)["type"] + "&>(\n" +
                        (*variables)["type_default_instance"] + "));\n")
@@ -343,7 +343,7 @@
     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) {
@@ -376,7 +376,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 +394,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(
diff --git a/src/google/protobuf/compiler/cpp/message_field.h b/src/google/protobuf/compiler/cpp/message_field.h
index 70c42c0..39efe28 100644
--- a/src/google/protobuf/compiler/cpp/message_field.h
+++ b/src/google/protobuf/compiler/cpp/message_field.h
@@ -38,8 +38,8 @@
 #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 +51,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 +83,6 @@
  protected:
   const bool implicit_weak_field_;
   const bool has_required_fields_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
 };
 
 class MessageOneofFieldGenerator : public MessageFieldGenerator {
@@ -91,6 +90,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 +108,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 +115,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 +138,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..a75d77a 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 "google/protobuf/unittest.pb.h"
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
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..e723346 100644
--- a/src/google/protobuf/compiler/cpp/move_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/move_unittest.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/stubs/common.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/unittest.pb.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
 #include <gtest/gtest.h>
 
 #if LANG_CXX11
diff --git a/src/google/protobuf/compiler/cpp/names.h b/src/google/protobuf/compiler/cpp/names.h
index 7404ac5..d83cabb 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 {
@@ -92,6 +92,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..7aab669 100644
--- a/src/google/protobuf/compiler/cpp/options.h
+++ b/src/google/protobuf/compiler/cpp/options.h
@@ -40,6 +40,7 @@
 namespace protobuf {
 namespace compiler {
 class AccessInfoMap;
+class SplitMap;
 
 namespace cpp {
 
@@ -58,6 +59,7 @@
 // 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 +82,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..74804b2 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 {
@@ -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..e4f057f 100644
--- a/src/google/protobuf/compiler/cpp/parse_function_generator.cc
+++ b/src/google/protobuf/compiler/cpp/parse_function_generator.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/compiler/cpp/parse_function_generator.h>
+#include "google/protobuf/compiler/cpp/parse_function_generator.h"
 
 #include <algorithm>
 #include <limits>
 #include <string>
 #include <utility>
 
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include "google/protobuf/wire_format.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"
 
 namespace google {
 namespace protobuf {
@@ -44,9 +47,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)
+      ;
+}
+
 std::vector<const FieldDescriptor*> GetOrderedFields(
     const Descriptor* descriptor, const Options& options) {
   std::vector<const FieldDescriptor*> ordered_fields;
@@ -66,364 +81,26 @@
   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 {
+    return {IsLazy(field, gen_->options_, gen_->scc_analyzer_),
+            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,
@@ -440,10 +117,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 +194,9 @@
   if (options_.tctable_mode == Options::kTCTableNever) {
     return false;
   }
+  if (HasSimpleBaseClass(descriptor_, options_)) {
+    return false;
+  }
   return true;
 }
 
@@ -547,7 +226,7 @@
 
   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");
 
@@ -604,10 +283,14 @@
   }
   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(),
+      // We add a +1 here to allow for a NUL termination character. It makes the
+      // codegen nicer.
+      tc_table_info_->field_name_data.size() + 1,
       field_num_to_entry_table.size16());
   if (should_generate_guarded_tctable()) {
     format.Outdent();
@@ -761,12 +444,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(),
+      tc_table_info_->field_name_data.size() + 1,  // See above for why +1
       field_num_to_entry_table.size16());
   {
     auto table_scope = format.ScopedIndent();
@@ -874,8 +558,46 @@
         {
           // 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::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");
@@ -898,145 +620,171 @@
     }
     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;
+      // For 1-byte tags we have a more optimized version of the varint parser
+      // that can hardcode the offset and has bit.
+      if (HasSuffixString(func_name, "V8S1") ||
+          HasSuffixString(func_name, "V32S1") ||
+          HasSuffixString(func_name, "V64S1")) {
+        std::string field_type = HasSuffixString(func_name, "V8S1") ? "bool"
+                                 : HasSuffixString(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",
+                                                  "IWeak"};
+      static_assert((fl::kRepGroup >> fl::kRepShift) == 1, "");
+      static_assert((fl::kRepLazy >> fl::kRepShift) == 2, "");
+      static_assert((fl::kRepIWeak >> fl::kRepShift) == 3, "");
+
+      if (auto* rep = kRepNames[rep_index]) {
+        format(" | ::_fl::kRep$1$", rep);
+      }
+
+      static constexpr const char* kXFormNames[] = {nullptr, "Default",
+                                                    "Table"};
+      static_assert((fl::kTvDefault >> fl::kTvShift) == 1, "");
+      static_assert((fl::kTvTable >> fl::kTvShift) == 2, "");
+
+      if (auto* xform = kXFormNames[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 +799,63 @@
       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;
+  // 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("\"");
-  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;
-  }
-  while (count & 7) {  // align to an 8-byte boundary
-    format("\\0");
-    ++count;
+  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 && sizes[0] != 0; p += *sizes++) {
+    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 +917,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 +933,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 +954,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 +983,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,7 +1002,7 @@
             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");
           }
@@ -1282,7 +1017,7 @@
                 "}\n"
                 "auto* lazy_field = $msg$$field$;\n",
                 field->containing_oneof()->name());
-          } else if (HasHasbit(field)) {
+          } else if (internal::cpp::HasHasbit(field)) {
             format(
                 "_Internal::set_has_$name$(&$has_bits$);\n"
                 "auto* lazy_field = &$msg$$field$;\n");
@@ -1356,12 +1091,12 @@
       {{"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) {
@@ -1371,14 +1106,17 @@
         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 +1143,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 +1162,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(
@@ -1612,112 +1350,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..b55feda 100644
--- a/src/google/protobuf/compiler/cpp/parse_function_generator.h
+++ b/src/google/protobuf/compiler/cpp/parse_function_generator.h
@@ -35,58 +35,18 @@
 #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/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/generated_message_tctable_gen.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 {
@@ -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.
@@ -166,7 +127,7 @@
   MessageSCCAnalyzer* scc_analyzer_;
   const Options& options_;
   std::map<std::string, std::string> variables_;
-  std::unique_ptr<TailCallTableInfo> tc_table_info_;
+  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..30bd374 100644
--- a/src/google/protobuf/compiler/cpp/plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/plugin_unittest.cc
@@ -36,13 +36,13 @@
 
 #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/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
 
 namespace google {
diff --git a/src/google/protobuf/compiler/cpp/primitive_field.cc b/src/google/protobuf/compiler/cpp/primitive_field.cc
index 6c92ede..bad8795 100644
--- a/src/google/protobuf/compiler/cpp/primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/primitive_field.cc
@@ -32,12 +32,13 @@
 //  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 "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/cpp/helpers.h"
 
 namespace google {
 namespace protobuf {
@@ -108,10 +109,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()));
@@ -328,7 +329,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 +436,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"
@@ -484,8 +487,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..b39c846 100644
--- a/src/google/protobuf/compiler/cpp/primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/primitive_field.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/cpp/field.h>
+#include "google/protobuf/compiler/cpp/field.h"
 
 namespace google {
 namespace protobuf {
@@ -49,6 +49,8 @@
  public:
   PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
                           const Options& options);
+  PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
+  PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
   ~PrimitiveFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -67,15 +69,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 +85,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 +116,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..eae9e77 100644
--- a/src/google/protobuf/compiler/cpp/service.cc
+++ b/src/google/protobuf/compiler/cpp/service.cc
@@ -32,293 +32,280 @@
 //  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 <map>
+#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 : 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", absl::StrCat(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..34b8914 100644
--- a/src/google/protobuf/compiler/cpp/service.h
+++ b/src/google/protobuf/compiler/cpp/service.h
@@ -38,60 +38,48 @@
 #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 "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 std::map<std::string, 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 +90,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_;
+  const Options* options_;
   std::map<std::string, std::string> vars_;
-  const Options& options_;
 
   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..3b05c36 100644
--- a/src/google/protobuf/compiler/cpp/string_field.cc
+++ b/src/google/protobuf/compiler/cpp/string_field.cc
@@ -32,12 +32,13 @@
 //  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 "google/protobuf/io/printer.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/descriptor.pb.h"
 
 
 namespace google {
@@ -52,12 +53,12 @@
                         const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
 
-  const std::string kNS = "::" + (*variables)["proto_ns"] + "::internal::";
+  const std::string kNS = "::" + ProtobufNamespace(options) + "::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);
 
@@ -67,7 +68,7 @@
     (*variables)["lazy_variable_args"] = "";
   } else {
     (*variables)["lazy_variable"] =
-        StrCat(QualifiedClassName(descriptor->containing_type(), options),
+        absl::StrCat(QualifiedClassName(descriptor->containing_type(), options),
                      "::", MakeDefaultFieldName(descriptor));
 
     (*variables)["default_string"] = (*variables)["lazy_variable"] + ".get()";
@@ -79,7 +80,6 @@
       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 +89,7 @@
   if (options.opensource_runtime) {
     (*variables)["string_piece"] = "::std::string";
   } else {
-    (*variables)["string_piece"] = "::StringPiece";
+    (*variables)["string_piece"] = "::absl::string_view";
   }
 }
 
@@ -286,7 +286,7 @@
       "$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"
         "    return nullptr;\n"
@@ -297,9 +297,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");
@@ -377,7 +375,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 +443,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,7 +451,7 @@
     format("new (&_this->$field$) ::_pbi::InlinedStringField();\n");
   }
 
-  if (HasHasbit(descriptor_)) {
+  if (internal::cpp::HasHasbit(descriptor_)) {
     format("if (from._internal_has_$name$()) {\n");
   } else {
     format("if (!from._internal_$name$().empty()) {\n");
@@ -554,13 +537,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(
@@ -592,7 +571,7 @@
   SetCommonOneofFieldVariables(descriptor, &variables_);
   variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
   variables_["oneof_index"] =
-      StrCat(descriptor->containing_oneof()->index());
+      absl::StrCat(descriptor->containing_oneof()->index());
 }
 
 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
@@ -737,7 +716,7 @@
   if (!options_.opensource_runtime) {
     format(
         "$deprecated_attr$void ${1$set_$name$$}$(int index, "
-        "StringPiece value);\n",
+        "absl::string_view value);\n",
         descriptor_);
   }
   format(
@@ -750,7 +729,7 @@
       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(
@@ -824,7 +803,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 +811,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"
@@ -861,14 +840,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"
diff --git a/src/google/protobuf/compiler/cpp/string_field.h b/src/google/protobuf/compiler/cpp/string_field.h
index db5f18b..02bee85 100644
--- a/src/google/protobuf/compiler/cpp/string_field.h
+++ b/src/google/protobuf/compiler/cpp/string_field.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/cpp/field.h>
+#include "google/protobuf/compiler/cpp/field.h"
 
 namespace google {
 namespace protobuf {
@@ -49,6 +49,8 @@
  public:
   StringFieldGenerator(const FieldDescriptor* descriptor,
                        const Options& options);
+  StringFieldGenerator(const StringFieldGenerator&) = delete;
+  StringFieldGenerator& operator=(const StringFieldGenerator&) = delete;
   ~StringFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -63,7 +65,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 +80,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 +100,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 +126,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..028248e 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;
   }
diff --git a/src/google/protobuf/compiler/cpp/unittest.cc b/src/google/protobuf/compiler/cpp/unittest.cc
index e2730d7..a52280d 100644
--- a/src/google/protobuf/compiler/cpp/unittest.cc
+++ b/src/google/protobuf/compiler/cpp/unittest.cc
@@ -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/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"
 
 #define MESSAGE_TEST_NAME MessageTest
 #define GENERATED_DESCRIPTOR_TEST_NAME GeneratedDescriptorTest
@@ -64,7 +64,7 @@
 #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..2d65ead 100644
--- a/src/google/protobuf/compiler/cpp/unittest.inc
+++ b/src/google/protobuf/compiler/cpp/unittest.inc
@@ -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/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"
+#include "google/protobuf/stubs/stl_util.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);
@@ -1822,7 +1821,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());
@@ -2223,4 +2222,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..ce29ea6
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/BUILD.bazel
@@ -0,0 +1,120 @@
+################################################################################
+# 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 = "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_names.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 = [
+        "//:protobuf",
+        "//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..315f595 100644
--- a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
@@ -39,19 +39,20 @@
 
 #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 "google/protobuf/stubs/strutil.h"
 #include <gtest/gtest.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"
+#include "google/protobuf/stubs/stl_util.h"
 
 namespace google {
 namespace protobuf {
@@ -70,8 +71,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);
   }
 };
 
@@ -178,12 +179,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..72a4c12 100644
--- a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
@@ -31,10 +31,15 @@
 // 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 "google/protobuf/stubs/strutil.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/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -54,10 +59,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..2b2bcf8 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -28,19 +28,27 @@
 // (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 <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 "google/protobuf/descriptor.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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_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 {
@@ -57,6 +65,9 @@
 
 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());
@@ -65,6 +76,9 @@
   std::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 +94,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..e808b7d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -28,22 +28,33 @@
 // (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 <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/descriptor.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_names.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/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 {
@@ -63,13 +74,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 +88,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;
   }
 
@@ -108,8 +119,8 @@
     (*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"];
     (*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"];
     if (presenceIndex_ != -1) {
-      std::string hasBitsNumber = StrCat(presenceIndex_ / 32);
-      std::string hasBitsMask = StrCat(1 << (presenceIndex_ % 32));
+      std::string hasBitsNumber = absl::StrCat(presenceIndex_ / 32);
+      std::string hasBitsMask = absl::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;
@@ -325,7 +336,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 +372,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 +383,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 +406,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 +422,7 @@
 }
 
 std::string FieldGeneratorBase::number() {
-  return StrCat(descriptor_->number());
+  return absl::StrCat(descriptor_->number());
 }
 
 std::string FieldGeneratorBase::capitalized_type_name() {
@@ -462,3 +473,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..9eecde9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -32,12 +32,20 @@
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
 
 #include <string>
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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 "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_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index 5ce0651..8a3286e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -28,20 +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 "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/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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_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/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..dd60eb7 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -32,28 +32,36 @@
 //  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/escaping.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.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_names.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/descriptor.pb.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_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 {
@@ -107,7 +115,7 @@
 }
 
 std::string StripDotProto(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);
 }
 
@@ -122,7 +130,7 @@
 // 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("/");
+    int lastslash = proto_file.find_last_of('/');
     std::string base = proto_file.substr(lastslash + 1);
     return UnderscoresToPascalCase(StripDotProto(base));
 }
@@ -144,6 +152,7 @@
                                    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') {
@@ -177,6 +186,23 @@
   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;
 }
 
@@ -200,18 +226,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 +255,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 +268,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 +302,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;
@@ -333,7 +359,7 @@
     // the C# namespace.
     classname = name.substr(file->package().size() + 1);
   }
-  result += StringReplace(classname, ".", ".Types.", true);
+  result += absl::StrReplaceAll(classname, {{".", ".Types."}});
   return "global::" + result;
 }
 
@@ -379,15 +405,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;
@@ -422,12 +463,13 @@
       return ""; // This will be ignored, because we've set an error.
     }
     namespace_suffix = ns.substr(base_namespace.length());
-    if (namespace_suffix.find(".") == 0) {
+    if (namespace_suffix.find('.') == 0) {
       namespace_suffix = namespace_suffix.substr(1);
     }
   }
 
-  std::string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
+  std::string namespace_dir =
+      absl::StrReplaceAll(namespace_suffix, {{".", "/"}});
   if (!namespace_dir.empty()) {
     namespace_dir += "/";
   }
@@ -597,3 +639,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..55660b7 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -36,14 +36,14 @@
 #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/descriptor.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"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -91,7 +91,9 @@
 
 int GetFixedSize(FieldDescriptor::Type type);
 
-std::string UnderscoresToCamelCase(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);
 
@@ -193,6 +195,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..34ea3e9 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -28,18 +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.
 
+#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/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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_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 {
@@ -90,7 +98,7 @@
 void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
   printer->Print(
       variables_,
-      "$name$_.Add(other.$name$_);\n");
+      "$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..993e9d6 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -28,26 +28,37 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#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 "google/protobuf/descriptor.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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_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_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"
 
-#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 {
@@ -161,7 +172,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 +184,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 +227,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 +251,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");
@@ -382,7 +393,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++) {
@@ -698,7 +709,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 +738,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 +788,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..9d70bd0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -28,21 +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/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/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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_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_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_names.h b/src/google/protobuf/compiler/csharp/csharp_names.h
index 67e53b6..61f4b7b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_names.h
+++ b/src/google/protobuf/compiler/csharp/csharp_names.h
@@ -39,10 +39,10 @@
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
 
 #include <string>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/common.h>
+#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 {
@@ -104,6 +104,6 @@
 }  // 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/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index e7d5116..f42ff90 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -28,19 +28,27 @@
 // (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 "google/protobuf/descriptor.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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_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 {
@@ -215,7 +223,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..b767c9d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
@@ -28,23 +28,33 @@
 // (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 "google/protobuf/descriptor.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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_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"
+#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"
 
-
-#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 +223,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 +275,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 +288,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 +301,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 +313,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 +338,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..0d4b639 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/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/importer.cc b/src/google/protobuf/compiler/importer.cc
index f1e26f8..287b22e 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 "google/protobuf/stubs/strutil.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.
+  std::string path_str;
   if (HasPrefixString(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) {
+static inline bool ContainsParentReference(absl::string_view path) {
   return path == ".." || HasPrefixString(path, "../") ||
-         HasSuffixString(path, "/..") || path.find("/../") != std::string::npos;
+         HasSuffixString(path, "/..") || absl::StrContains(path, "/../");
 }
 
 // Maps a file from an old location to a new one.  Typically, old_prefix is
@@ -332,9 +327,9 @@
 //   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)) {
@@ -345,15 +340,15 @@
       // 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)) {
     // 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..bab4b73 100644
--- a/src/google/protobuf/compiler/importer.h
+++ b/src/google/protobuf/compiler/importer.h
@@ -42,12 +42,12 @@
 #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 +159,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 +190,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 +208,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 +216,22 @@
 // below.
 class PROTOBUF_EXPORT SourceTree {
  public:
-  inline SourceTree() {}
+  SourceTree() {}
+  SourceTree(const SourceTree&) = delete;
+  SourceTree& operator=(const SourceTree&) = delete;
   virtual ~SourceTree();
 
+  // This is a temporary typedef alias to allow migrating the argument type of
+  // Open in an atomic change without touching certain directories which are
+  // restricted for various reasons.  This must match the argument type used
+  // below.
+  using SourceTreeOpenArgumentType = absl::string_view;
+
   // 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 +239,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 +247,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 +267,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 +298,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 +317,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..21044c7 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -32,23 +32,23 @@
 //  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/io/zero_copy_stream_impl.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/strings/substitute.h"
+
+#include "google/protobuf/stubs/strutil.h"
 
 namespace google {
 namespace protobuf {
@@ -74,13 +74,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 +93,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..06d90f6
--- /dev/null
+++ b/src/google/protobuf/compiler/java/BUILD.bazel
@@ -0,0 +1,140 @@
+################################################################################
+# 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 = "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",
+        "helpers.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",
+        "name_resolver.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",
+        "helpers.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",
+        "name_resolver.h",
+        "names.h",
+        "options.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 = [
+        "//:protobuf",
+        "//src/google/protobuf/compiler:code_generator",
+        "@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..d9bc0fe 100644
--- a/src/google/protobuf/compiler/java/context.cc
+++ b/src/google/protobuf/compiler/java/context.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/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 "google/protobuf/descriptor.h"
+#include "google/protobuf/stubs/strutil.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"
 
 namespace google {
 namespace protobuf {
@@ -43,7 +43,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);
 }
 
@@ -159,8 +159,8 @@
     // 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 +169,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..4697c8c 100644
--- a/src/google/protobuf/compiler/java/context.h
+++ b/src/google/protobuf/compiler/java/context.h
@@ -31,12 +31,12 @@
 #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/options.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -65,6 +65,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,12 +99,11 @@
       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);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/doc_comment.cc b/src/google/protobuf/compiler/java/doc_comment.cc
index 066bff6..a515eb2 100644
--- a/src/google/protobuf/compiler/java/doc_comment.cc
+++ b/src/google/protobuf/compiler/java/doc_comment.cc
@@ -32,13 +32,16 @@
 //  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 "google/protobuf/io/printer.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -103,26 +106,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 +175,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 +211,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 +248,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 +286,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 +344,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 +414,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 +470,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 +501,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 +511,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..f3e1b42 100644
--- a/src/google/protobuf/compiler/java/enum.cc
+++ b/src/google/protobuf/compiler/java/enum.cc
@@ -32,21 +32,22 @@
 //  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 "google/protobuf/io/printer.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/descriptor.pb.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -80,6 +81,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",
@@ -101,8 +106,8 @@
   for (int i = 0; i < canonical_values_.size(); i++) {
     std::map<std::string, 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");
@@ -144,7 +149,7 @@
   for (int i = 0; i < descriptor_->value_count(); i++) {
     std::map<std::string, 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 +186,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 +221,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 +291,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 +304,7 @@
                   .no_standard_descriptor_accessor()
               ? "getDefaultInstance().getDescriptorForType()"
               : "getDescriptor()",
-          "index", StrCat(descriptor_->index()));
+          "index", absl::StrCat(descriptor_->index()));
     }
 
     printer->Print(
@@ -394,4 +408,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..8868e47 100644
--- a/src/google/protobuf/compiler/java/enum.h
+++ b/src/google/protobuf/compiler/java/enum.h
@@ -37,7 +37,7 @@
 
 #include <string>
 #include <vector>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,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 +90,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 ed3594c..ea74d8b 100644
--- a/src/google/protobuf/compiler/java/enum_field.cc
+++ b/src/google/protobuf/compiler/java/enum_field.cc
@@ -32,24 +32,24 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/enum_field.h>
+#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 <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 "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -61,20 +61,22 @@
 void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
                       int builderBitIndex, const FieldGeneratorInfo* info,
                       ClassNameResolver* name_resolver,
-                      std::map<std::string, std::string>* variables) {
+                      std::map<std::string, std::string>* variables,
+                      Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->enum_type());
-  (*variables)["kt_type"] = (*variables)["type"];
+  (*variables)["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
@@ -85,13 +87,6 @@
           ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
                 " is deprecated\") "
           : "";
-  (*variables)["on_changed"] = "onChanged();";
-  // Use deprecated valueOf() method to be compatible with old generated code
-  // for v2.5.0/v2.6.1.
-  // TODO(xiaofeng): Use "forNumber" when we no longer support compatibility
-  // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations.
-  (*variables)["for_number"] = "valueOf";
-
   if (HasHasbit(descriptor)) {
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
@@ -150,7 +145,7 @@
     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
   SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
-                   &variables_);
+                   &variables_, context);
 }
 
 ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
@@ -204,8 +199,7 @@
   printer->Print(variables_,
                  "@java.lang.Override $deprecation$public $type$ "
                  "${$get$capitalized_name$$}$() {\n"
-                 "  @SuppressWarnings(\"deprecation\")\n"
-                 "  $type$ result = $type$.$for_number$($name$_);\n"
+                 "  $type$ result = $type$.forNumber($name$_);\n"
                  "  return result == null ? $unknown$ : result;\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -238,7 +232,7 @@
                    "${$set$capitalized_name$Value$}$(int value) {\n"
                    "  $set_has_field_bit_builder$\n"
                    "  $name$_ = value;\n"
-                   "  $on_changed$\n"
+                   "  onChanged();\n"
                    "  return this;\n"
                    "}\n");
     printer->Annotate("{", "}", descriptor_);
@@ -247,8 +241,7 @@
   printer->Print(variables_,
                  "@java.lang.Override\n"
                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
-                 "  @SuppressWarnings(\"deprecation\")\n"
-                 "  $type$ result = $type$.$for_number$($name$_);\n"
+                 "  $type$ result = $type$.forNumber($name$_);\n"
                  "  return result == null ? $unknown$ : result;\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -262,7 +255,7 @@
                  "  }\n"
                  "  $set_has_field_bit_builder$\n"
                  "  $name$_ = value.getNumber();\n"
-                 "  $on_changed$\n"
+                 "  onChanged();\n"
                  "  return this;\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -273,7 +266,7 @@
       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
       "  $clear_has_field_bit_builder$\n"
       "  $name$_ = $default_number$;\n"
-      "  $on_changed$\n"
+      "  onChanged();\n"
       "  return this;\n"
       "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -281,7 +274,7 @@
 
 void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$ var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -291,15 +284,28 @@
                  "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
                  "  }\n");
 
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(
+        variables_,
+        "$kt_deprecation$ 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_,
                  "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_,
         "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -364,8 +370,7 @@
   } else {
     printer->Print(variables_,
                    "int rawValue = input.readEnum();\n"
-                   "  @SuppressWarnings(\"deprecation\")\n"
-                   "$type$ value = $type$.$for_number$(rawValue);\n"
+                   "$type$ value = $type$.forNumber(rawValue);\n"
                    "if (value == null) {\n"
                    "  unknownFields.mergeVarintField($number$, rawValue);\n"
                    "} else {\n"
@@ -453,8 +458,7 @@
   printer->Print(variables_,
                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
                  "  if ($has_oneof_case_message$) {\n"
-                 "    @SuppressWarnings(\"deprecation\")\n"
-                 "    $type$ result = $type$.$for_number$(\n"
+                 "    $type$ result = $type$.forNumber(\n"
                  "        (java.lang.Integer) $oneof_name$_);\n"
                  "    return result == null ? $unknown$ : result;\n"
                  "  }\n"
@@ -493,7 +497,7 @@
                    "${$set$capitalized_name$Value$}$(int value) {\n"
                    "  $set_oneof_case_message$;\n"
                    "  $oneof_name$_ = value;\n"
-                   "  $on_changed$\n"
+                   "  onChanged();\n"
                    "  return this;\n"
                    "}\n");
     printer->Annotate("{", "}", descriptor_);
@@ -503,8 +507,7 @@
                  "@java.lang.Override\n"
                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
                  "  if ($has_oneof_case_message$) {\n"
-                 "    @SuppressWarnings(\"deprecation\")\n"
-                 "    $type$ result = $type$.$for_number$(\n"
+                 "    $type$ result = $type$.forNumber(\n"
                  "        (java.lang.Integer) $oneof_name$_);\n"
                  "    return result == null ? $unknown$ : result;\n"
                  "  }\n"
@@ -521,7 +524,7 @@
                  "  }\n"
                  "  $set_oneof_case_message$;\n"
                  "  $oneof_name$_ = value.getNumber();\n"
-                 "  $on_changed$\n"
+                 "  onChanged();\n"
                  "  return this;\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -533,7 +536,7 @@
       "  if ($has_oneof_case_message$) {\n"
       "    $clear_oneof_case_message$;\n"
       "    $oneof_name$_ = null;\n"
-      "    $on_changed$\n"
+      "    onChanged();\n"
       "  }\n"
       "  return this;\n"
       "}\n");
@@ -570,8 +573,7 @@
   } else {
     printer->Print(variables_,
                    "int rawValue = input.readEnum();\n"
-                   "@SuppressWarnings(\"deprecation\")\n"
-                   "$type$ value = $type$.$for_number$(rawValue);\n"
+                   "$type$ value = $type$.forNumber(rawValue);\n"
                    "if (value == null) {\n"
                    "  unknownFields.mergeVarintField($number$, rawValue);\n"
                    "} else {\n"
@@ -637,7 +639,7 @@
     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
   SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
-                   &variables_);
+                   &variables_, context);
 }
 
 RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
@@ -685,8 +687,7 @@
       "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
       "            java.lang.Integer, $type$>() {\n"
       "          public $type$ convert(java.lang.Integer from) {\n"
-      "            @SuppressWarnings(\"deprecation\")\n"
-      "            $type$ result = $type$.$for_number$(from);\n"
+      "            $type$ result = $type$.forNumber(from);\n"
       "            return result == null ? $unknown$ : result;\n"
       "          }\n"
       "        };\n");
@@ -802,7 +803,7 @@
                  "  }\n"
                  "  ensure$capitalized_name$IsMutable();\n"
                  "  $name$_.set(index, value.getNumber());\n"
-                 "  $on_changed$\n"
+                 "  onChanged();\n"
                  "  return this;\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -816,7 +817,7 @@
                  "  }\n"
                  "  ensure$capitalized_name$IsMutable();\n"
                  "  $name$_.add(value.getNumber());\n"
-                 "  $on_changed$\n"
+                 "  onChanged();\n"
                  "  return this;\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -829,7 +830,7 @@
                  "  for ($type$ value : values) {\n"
                  "    $name$_.add(value.getNumber());\n"
                  "  }\n"
-                 "  $on_changed$\n"
+                 "  onChanged();\n"
                  "  return this;\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -840,7 +841,7 @@
       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
       "  $name$_ = java.util.Collections.emptyList();\n"
       "  $clear_mutable_bit_builder$;\n"
-      "  $on_changed$\n"
+      "  onChanged();\n"
       "  return this;\n"
       "}\n");
   printer->Annotate("{", "}", descriptor_);
@@ -870,7 +871,7 @@
         "    int index, int value) {\n"
         "  ensure$capitalized_name$IsMutable();\n"
         "  $name$_.set(index, value);\n"
-        "  $on_changed$\n"
+        "  onChanged();\n"
         "  return this;\n"
         "}\n");
     printer->Annotate("{", "}", descriptor_);
@@ -881,7 +882,7 @@
                    "${$add$capitalized_name$Value$}$(int value) {\n"
                    "  ensure$capitalized_name$IsMutable();\n"
                    "  $name$_.add(value);\n"
-                   "  $on_changed$\n"
+                   "  onChanged();\n"
                    "  return this;\n"
                    "}\n");
     printer->Annotate("{", "}", descriptor_);
@@ -895,7 +896,7 @@
         "  for (int value : values) {\n"
         "    $name$_.add(value);\n"
         "  }\n"
-        "  $on_changed$\n"
+        "  onChanged();\n"
         "  return this;\n"
         "}\n");
     printer->Annotate("{", "}", descriptor_);
@@ -935,7 +936,7 @@
                  "    ensure$capitalized_name$IsMutable();\n"
                  "    $name$_.addAll(other.$name$_);\n"
                  "  }\n"
-                 "  $on_changed$\n"
+                 "  onChanged();\n"
                  "}\n");
 }
 
@@ -967,8 +968,7 @@
     printer->Print(
         variables_,
         "int rawValue = input.readEnum();\n"
-        "@SuppressWarnings(\"deprecation\")\n"
-        "$type$ value = $type$.$for_number$(rawValue);\n"
+        "$type$ value = $type$.forNumber(rawValue);\n"
         "if (value == null) {\n"
         "  unknownFields.mergeVarintField($number$, rawValue);\n"
         "} else {\n"
@@ -1088,7 +1088,7 @@
       "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$ val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -1099,7 +1099,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"
@@ -1110,7 +1110,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"
@@ -1122,7 +1122,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"
@@ -1133,7 +1133,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1146,7 +1146,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1158,7 +1158,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"
@@ -1178,4 +1178,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.h b/src/google/protobuf/compiler/java/enum_field.h
index d2bc8d6..db2aa75 100644
--- a/src/google/protobuf/compiler/java/enum_field.h
+++ b/src/google/protobuf/compiler/java/enum_field.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -61,6 +61,9 @@
   explicit ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
                                        int messageBitIndex, int builderBitIndex,
                                        Context* context);
+  ImmutableEnumFieldGenerator(const ImmutableEnumFieldGenerator&) = delete;
+  ImmutableEnumFieldGenerator& operator=(const ImmutableEnumFieldGenerator&) =
+      delete;
   ~ImmutableEnumFieldGenerator() override;
 
   // implements ImmutableFieldGenerator
@@ -90,9 +93,6 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, std::string> variables_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator);
 };
 
 class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
@@ -100,6 +100,10 @@
   ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor,
                                    int messageBitIndex, int builderBitIndex,
                                    Context* context);
+  ImmutableEnumOneofFieldGenerator(const ImmutableEnumOneofFieldGenerator&) =
+      delete;
+  ImmutableEnumOneofFieldGenerator& operator=(
+      const ImmutableEnumOneofFieldGenerator&) = delete;
   ~ImmutableEnumOneofFieldGenerator() override;
 
   void GenerateMembers(io::Printer* printer) const override;
@@ -111,9 +115,6 @@
   void GenerateSerializedSizeCode(io::Printer* printer) const override;
   void GenerateEqualsCode(io::Printer* printer) const override;
   void GenerateHashCode(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator);
 };
 
 class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
@@ -121,6 +122,10 @@
   explicit RepeatedImmutableEnumFieldGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex,
       int builderBitIndex, Context* context);
+  RepeatedImmutableEnumFieldGenerator(
+      const RepeatedImmutableEnumFieldGenerator&) = delete;
+  RepeatedImmutableEnumFieldGenerator& operator=(
+      const RepeatedImmutableEnumFieldGenerator&) = delete;
   ~RepeatedImmutableEnumFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
@@ -150,8 +155,6 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, std::string> variables_;
   ClassNameResolver* name_resolver_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/enum_field_lite.cc b/src/google/protobuf/compiler/java/enum_field_lite.cc
index 6fe683f..713f805 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 "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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -68,20 +69,22 @@
 void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
                       int builderBitIndex, const FieldGeneratorInfo* info,
                       ClassNameResolver* name_resolver,
-                      std::map<std::string, std::string>* variables) {
+                      std::map<std::string, std::string>* variables,
+                      Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->enum_type());
-  (*variables)["kt_type"] = (*variables)["type"];
+  (*variables)["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
@@ -95,6 +98,12 @@
   (*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);
 
@@ -142,7 +151,7 @@
       name_resolver_(context->GetNameResolver()) {
   SetEnumVariables(descriptor, messageBitIndex, 0,
                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
-                   &variables_);
+                   &variables_, context);
 }
 
 ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
@@ -169,6 +178,20 @@
 
 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 +309,7 @@
 
 void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -296,15 +319,28 @@
                  "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
                  "  }\n");
 
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(
+        variables_,
+        "$kt_deprecation$ 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_,
                  "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_,
         "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -501,7 +537,7 @@
       name_resolver_(context->GetNameResolver()) {
   SetEnumVariables(descriptor, messageBitIndex, 0,
                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
-                   &variables_);
+                   &variables_, context);
 }
 
 RepeatedImmutableEnumFieldLiteGenerator::
@@ -537,6 +573,13 @@
 
 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"
@@ -830,7 +873,7 @@
       "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$ val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -841,7 +884,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 +895,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 +907,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 +918,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -888,7 +931,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -900,7 +943,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 +963,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..8d7a7d1 100644
--- a/src/google/protobuf/compiler/java/enum_field_lite.h
+++ b/src/google/protobuf/compiler/java/enum_field_lite.h
@@ -39,7 +39,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.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
@@ -83,9 +87,6 @@
   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 ------------------------------------
@@ -128,8 +134,6 @@
   std::map<std::string, 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..a04f814 100644
--- a/src/google/protobuf/compiler/java/enum_lite.cc
+++ b/src/google/protobuf/compiler/java/enum_lite.cc
@@ -32,19 +32,19 @@
 //  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 "google/protobuf/io/printer.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/descriptor.pb.h"
 
 namespace google {
 namespace protobuf {
@@ -89,7 +89,7 @@
   for (int i = 0; i < canonical_values_.size(); i++) {
     std::map<std::string, 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");
@@ -123,7 +123,7 @@
   for (int i = 0; i < descriptor_->value_count(); i++) {
     std::map<std::string, 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 +153,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 +182,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 +221,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..13306b1 100644
--- a/src/google/protobuf/compiler/java/enum_lite.h
+++ b/src/google/protobuf/compiler/java/enum_lite.h
@@ -37,7 +37,7 @@
 
 #include <string>
 #include <vector>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,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 +88,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..0e42a01 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 "google/protobuf/io/printer.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"
 
 // 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,19 @@
 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_pointer, Context* context) {
   std::map<std::string, 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";
@@ -116,7 +120,7 @@
   std::map<std::string, 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 +160,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 +178,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..b9dc995 100644
--- a/src/google/protobuf/compiler/java/extension.h
+++ b/src/google/protobuf/compiler/java/extension.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/stubs/common.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;
@@ -79,19 +81,20 @@
   virtual int GenerateRegistrationCode(io::Printer* printer) = 0;
 
  protected:
-  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);
+  static void InitTemplateVars(const FieldDescriptor* descriptor,
+                               const std::string& scope, bool immutable,
+                               ClassNameResolver* name_resolver,
+                               std::map<std::string, 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..4c3b83a 100644
--- a/src/google/protobuf/compiler/java/extension_lite.cc
+++ b/src/google/protobuf/compiler/java/extension_lite.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/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 "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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -47,7 +47,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());
@@ -62,7 +64,7 @@
   std::map<std::string, 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 +119,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..015f2ee 100644
--- a/src/google/protobuf/compiler/java/extension_lite.h
+++ b/src/google/protobuf/compiler/java/extension_lite.h
@@ -34,8 +34,8 @@
 #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 +49,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 +67,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 6313a2a..dd5e16c 100644
--- a/src/google/protobuf/compiler/java/field.cc
+++ b/src/google/protobuf/compiler/java/field.cc
@@ -32,27 +32,28 @@
 //  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 <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 "google/protobuf/io/printer.h"
+#include "google/protobuf/stubs/strutil.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"
 
 
 namespace google {
@@ -250,7 +251,7 @@
   (*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
@@ -285,13 +286,13 @@
   (*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,
diff --git a/src/google/protobuf/compiler/java/field.h b/src/google/protobuf/compiler/java/field.h
index 6ac01b9..4743f59 100644
--- a/src/google/protobuf/compiler/java/field.h
+++ b/src/google/protobuf/compiler/java/field.h
@@ -40,9 +40,10 @@
 #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 "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 GetNumBitsForMessage() const = 0;
@@ -90,14 +93,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;
@@ -110,9 +113,6 @@
   virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0;
 
   virtual std::string GetBoxedType() const = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator);
 };
 
 
@@ -121,6 +121,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;
@@ -128,8 +130,6 @@
  private:
   const Descriptor* descriptor_;
   std::vector<std::unique_ptr<FieldGeneratorType>> field_generators_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
 
 template <typename FieldGeneratorType>
diff --git a/src/google/protobuf/compiler/java/file.cc b/src/google/protobuf/compiler/java/file.cc
index cf27703..20949d0 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 <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 "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 "absl/strings/str_cat.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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -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;
@@ -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);
@@ -547,7 +555,7 @@
         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 +568,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(
@@ -704,15 +712,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\")");
     if (!java_package_.empty()) {
       printer.Print(
           "package $package$;\n"
           "\n",
-          "package", java_package_);
+          "package", EscapeKotlinKeywords(java_package_));
     }
 
     generator->GenerateKotlinMembers(&printer);
@@ -736,4 +747,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..bf1e23b 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.
@@ -114,8 +116,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..52bca03 100644
--- a/src/google/protobuf/compiler/java/generator.cc
+++ b/src/google/protobuf/compiler/java/generator.cc
@@ -32,23 +32,23 @@
 //  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 "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 <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/strutil.h"
 
 namespace google {
 namespace protobuf {
@@ -74,6 +74,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..fc7755c 100644
--- a/src/google/protobuf/compiler/java/generator.h
+++ b/src/google/protobuf/compiler/java/generator.h
@@ -38,10 +38,10 @@
 #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 +55,8 @@
 class PROTOC_EXPORT JavaGenerator : public CodeGenerator {
  public:
   JavaGenerator();
+  JavaGenerator(const JavaGenerator&) = delete;
+  JavaGenerator& operator=(const JavaGenerator&) = delete;
   ~JavaGenerator() override;
 
   // implements CodeGenerator ----------------------------------------
@@ -63,8 +65,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 +78,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..625ff18 100644
--- a/src/google/protobuf/compiler/java/helpers.cc
+++ b/src/google/protobuf/compiler/java/helpers.cc
@@ -32,25 +32,30 @@
 //  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 "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/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/stubs/stringprintf.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/compiler/java/names.h"
+#include "google/protobuf/descriptor.pb.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -66,52 +71,51 @@
     "// -------------------------------------------------------------------\n";
 
 namespace {
+const char* DefaultPackage(Options options) {
+  return options.opensource_runtime ? "" : "com.google.protos";
+}
 
-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 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) {
-  for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
-    if (UnderscoresToCamelCase(field_name, true) == kForbiddenWordList[i]) {
-      return true;
-    }
-  }
-  return false;
+  // 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) {
@@ -136,7 +140,8 @@
 }  // 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;
   }
@@ -155,8 +160,8 @@
                             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 +172,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,
@@ -257,7 +262,7 @@
 
 std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) {
   std::string name = UnderscoresToCamelCase(field);
-  if (kReservedNames->find(name) != kReservedNames->end()) {
+  if (IsReservedName(name)) {
     return name + "_";
   }
   return name;
@@ -265,22 +270,35 @@
 
 // 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,17 +310,17 @@
 }
 
 std::string FileClassName(const FileDescriptor* file, bool immutable) {
-  ClassNameResolver name_resolver;
-  return name_resolver.GetFileClassName(file, immutable);
+  return ClassNameResolver().GetFileClassName(file, immutable);
 }
 
-std::string FileJavaPackage(const FileDescriptor* file, bool immutable) {
+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 = kDefaultPackage;
+    result = DefaultPackage(options);
     if (!file->package().empty()) {
       if (!result.empty()) result += '.';
       result += file->package();
@@ -312,12 +330,12 @@
   return result;
 }
 
-std::string FileJavaPackage(const FileDescriptor* file) {
-  return FileJavaPackage(file, true /* immutable */);
+std::string FileJavaPackage(const FileDescriptor* file, Options options) {
+  return FileJavaPackage(file, true /* immutable */, options);
 }
 
 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;
 }
@@ -364,7 +382,7 @@
 
 std::string FieldConstantName(const FieldDescriptor* field) {
   std::string name = field->name() + "_FIELD_NUMBER";
-  ToUpper(&name);
+  absl::AsciiStrToUpper(&name);
   return name;
 }
 
@@ -519,7 +537,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 +600,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();
@@ -626,21 +644,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 +731,7 @@
 
 std::string GetBitFieldName(int index) {
   std::string varName = "bitField";
-  varName += StrCat(index);
+  varName += absl::StrCat(index);
   varName += "_";
   return varName;
 }
@@ -806,7 +824,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 +942,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 +977,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);
 }
 
@@ -1112,4 +1131,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..eb16096 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 "google/protobuf/io/printer.h"
+#include "google/protobuf/descriptor.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/compiler/java/context.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 {
@@ -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,7 +69,8 @@
 // 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.
@@ -113,11 +119,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);
@@ -206,7 +216,8 @@
     PrintGeneratedAnnotation(printer, '$',
                              context->options().annotate_code
                                  ? AnnotationFileName(descriptor, suffix)
-                                 : "");
+                                 : "",
+                             context->options());
   }
 }
 
@@ -251,10 +262,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 +346,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 +485,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..2058371 100644
--- a/src/google/protobuf/compiler/java/java_generator.h
+++ b/src/google/protobuf/compiler/java/java_generator.h
@@ -1,6 +1,6 @@
 #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..3470ccb 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 {
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 bc48f61..66d7fbb 100644
--- a/src/google/protobuf/compiler/java/map_field.cc
+++ b/src/google/protobuf/compiler/java/map_field.cc
@@ -28,16 +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/java/map_field.h>
+#include "google/protobuf/compiler/java/map_field.h"
 
-#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/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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -102,7 +102,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 +118,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\"); }"
@@ -127,10 +133,13 @@
   if (valueJavaType == JAVATYPE_ENUM) {
     // We store enums as Integers internally.
     (*variables)["value_type"] = "int";
+    (*variables)["value_type_pass_through_nullness"] =
+        (*variables)["value_type"];
     (*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);
 
@@ -144,7 +153,7 @@
     } 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);
@@ -156,7 +165,7 @@
     (*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"];
@@ -192,7 +201,9 @@
 ImmutableMapFieldGenerator::ImmutableMapFieldGenerator(
     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
     Context* context)
-    : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+    : descriptor_(descriptor),
+      name_resolver_(context->GetNameResolver()),
+      context_(context) {
   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
                       context->GetFieldGeneratorInfo(descriptor), context,
                       &variables_);
@@ -216,14 +227,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_,
@@ -262,9 +275,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_,
@@ -274,14 +288,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"
@@ -398,18 +414,20 @@
                  "}\n");
   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"
-        "  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"
+          "  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"
@@ -434,17 +452,19 @@
         "}\n");
     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"
-          "  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"
+            "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+            "}\n");
+        printer->Annotate("{", "}", descriptor_);
+      }
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
@@ -470,17 +490,19 @@
       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"
-        "  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"
+          "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "$deprecation$"
@@ -527,17 +549,20 @@
       "}\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.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"
@@ -609,9 +634,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$().getMap();\n"
@@ -636,17 +662,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"
@@ -661,9 +689,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$().getMap();\n"
@@ -701,7 +730,7 @@
       "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$ val $kt_name$: "
@@ -713,7 +742,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"
@@ -723,7 +752,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"
@@ -735,7 +764,7 @@
       "     put(key, value)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -746,7 +775,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"
@@ -758,7 +787,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"
@@ -891,4 +920,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.h b/src/google/protobuf/compiler/java/map_field.h
index 7fee10a..646c35a 100644
--- a/src/google/protobuf/compiler/java/map_field.h
+++ b/src/google/protobuf/compiler/java/map_field.h
@@ -31,7 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -71,6 +71,7 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, 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 4f2766e..e116d1e 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/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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -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,10 +130,13 @@
   if (GetJavaType(value) == JAVATYPE_ENUM) {
     // We store enums as Integers internally.
     (*variables)["value_type"] = "int";
+    (*variables)["value_type_pass_through_nullness"] =
+        (*variables)["value_type"];
     (*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);
 
@@ -143,7 +150,7 @@
     } 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);
@@ -155,7 +162,7 @@
     (*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"];
@@ -201,14 +208,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 +256,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 +269,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 +315,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 +362,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 +394,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 +451,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 +479,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 +507,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 +622,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 +730,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 +780,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 +808,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 +874,7 @@
       "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$ val $kt_name$: "
@@ -853,7 +886,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 +896,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 +908,7 @@
       "     put(key, value)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -886,7 +919,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 +931,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 +957,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..46a2d9f 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 {
diff --git a/src/google/protobuf/compiler/java/message.cc b/src/google/protobuf/compiler/java/message.cc
index 0cc6171..52768bb 100644
--- a/src/google/protobuf/compiler/java/message.cc
+++ b/src/google/protobuf/compiler/java/message.cc
@@ -32,7 +32,7 @@
 //  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>
@@ -40,24 +40,27 @@
 #include <memory>
 #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/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"
+#include "google/protobuf/stubs/strutil.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.pb.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -114,7 +117,7 @@
 
   std::map<std::string, 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());
@@ -158,7 +161,7 @@
   int bytecode_estimate = 0;
   std::map<std::string, 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());
@@ -260,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"
@@ -292,7 +298,7 @@
   for (auto oneof : 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",
@@ -319,6 +325,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) {
@@ -332,7 +342,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());
@@ -346,7 +356,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");
@@ -424,7 +434,9 @@
     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"
@@ -432,46 +444,52 @@
     // 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"
@@ -481,17 +499,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_)) {
@@ -502,7 +521,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");
@@ -582,13 +601,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"
@@ -623,19 +635,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("unknownFields.writeAsMessageSetTo(output);\n");
@@ -765,17 +766,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) {
@@ -847,7 +837,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(
@@ -1005,6 +995,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(
@@ -1012,6 +1006,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"
@@ -1051,7 +1047,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");
@@ -1125,7 +1121,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).GenerateHashCode(printer);
       printer->Print("break;\n");
@@ -1229,7 +1225,7 @@
         field->number(), WireFormat::WireTypeForFieldType(field->type()));
 
     printer->Print("case $tag$: {\n", "tag",
-                   StrCat(static_cast<int32_t>(tag)));
+                   absl::StrCat(static_cast<int32_t>(tag)));
     printer->Indent();
 
     field_generators_.get(field).GenerateParsingCode(printer);
@@ -1245,7 +1241,7 @@
       uint32_t packed_tag = WireFormatLite::MakeTag(
           field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
       printer->Print("case $tag$: {\n", "tag",
-                     StrCat(static_cast<int32_t>(packed_tag)));
+                     absl::StrCat(static_cast<int32_t>(packed_tag)));
       printer->Indent();
 
       field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
@@ -1426,7 +1422,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();
 
@@ -1447,7 +1444,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) {
@@ -1460,8 +1457,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"
       "inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> "
       "kotlin.Unit): "
       "$message$ "
@@ -1469,9 +1473,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("object $name$Kt {\n", "name", descriptor_->name());
   printer->Indent();
   GenerateKotlinDsl(printer);
@@ -1486,15 +1494,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"
       "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;
@@ -1512,18 +1527,21 @@
       printer->Print(
           "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"
@@ -1727,7 +1745,8 @@
       "@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"
@@ -1753,4 +1772,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..0380eab 100644
--- a/src/google/protobuf/compiler/java/message.h
+++ b/src/google/protobuf/compiler/java/message.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.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
@@ -93,14 +95,14 @@
  protected:
   const Descriptor* descriptor_;
   std::set<const OneofDescriptor*> oneofs_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
 };
 
 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 2366c0c..0184ee8 100644
--- a/src/google/protobuf/compiler/java/message_builder.cc
+++ b/src/google/protobuf/compiler/java/message_builder.cc
@@ -32,29 +32,31 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/message_builder.h>
+#include "google/protobuf/compiler/java/message_builder.h"
 
 #include <algorithm>
 #include <map>
 #include <memory>
 #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 "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 "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/name_resolver.h"
+#include "google/protobuf/descriptor.pb.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -127,7 +129,7 @@
     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"
@@ -168,24 +170,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"
@@ -231,7 +235,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(
@@ -256,7 +260,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(
@@ -443,75 +447,77 @@
       "\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
-  // 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) {
+  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 <Type> Builder setExtension(\n"
-        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
-        "        $classname$, Type> extension,\n"
-        "    Type value) {\n"
-        "  return super.setExtension(extension, value);\n"
+        "public Builder clone() {\n"
+        "  return super.clone();\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"
+        "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 <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"
+        "public Builder clearField(\n"
+        "    com.google.protobuf.Descriptors.FieldDescriptor field) {\n"
+        "  return super.clearField(field);\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_));
+        "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_));
+    }
   }
 
   // -----------------------------------------------------------------
@@ -554,7 +560,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");
@@ -566,7 +572,7 @@
           "  break;\n"
           "}\n",
           "cap_oneof_name",
-          ToUpper(context_->GetOneofGeneratorInfo(oneof)->name));
+          absl::AsciiStrToUpper(context_->GetOneofGeneratorInfo(oneof)->name));
       printer->Outdent();
       printer->Print("}\n");
     }
@@ -714,4 +720,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.h b/src/google/protobuf/compiler/java/message_builder.h
index f9c9a00..5ecbb91 100644
--- a/src/google/protobuf/compiler/java/message_builder.h
+++ b/src/google/protobuf/compiler/java/message_builder.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.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);
@@ -78,8 +80,6 @@
   ClassNameResolver* name_resolver_;
   FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
   std::set<const OneofDescriptor*> oneofs_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator);
 };
 
 }  // 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..c444794 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 <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 "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 "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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -100,7 +101,7 @@
     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,
@@ -153,4 +154,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..f21aec6 100644
--- a/src/google/protobuf/compiler/java/message_builder_lite.h
+++ b/src/google/protobuf/compiler/java/message_builder_lite.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.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);
@@ -75,8 +78,6 @@
   ClassNameResolver* name_resolver_;
   FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
   std::set<const OneofDescriptor*> oneofs_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/message_field.cc b/src/google/protobuf/compiler/java/message_field.cc
index f3833e9..32da1b7 100644
--- a/src/google/protobuf/compiler/java/message_field.cc
+++ b/src/google/protobuf/compiler/java/message_field.cc
@@ -32,21 +32,21 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/message_field.h>
+#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 <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"
+#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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -59,12 +59,13 @@
 void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
                          int builderBitIndex, const FieldGeneratorInfo* info,
                          ClassNameResolver* name_resolver,
-                         std::map<std::string, std::string>* variables) {
+                         std::map<std::string, std::string>* variables,
+                         Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
-  (*variables)["kt_type"] = (*variables)["type"];
+  (*variables)["kt_type"] = EscapeKotlinKeywords((*variables)["type"]);
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->message_type());
   (*variables)["group_or_message"] =
@@ -82,8 +83,10 @@
   (*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.
@@ -133,10 +136,12 @@
 ImmutableMessageFieldGenerator::ImmutableMessageFieldGenerator(
     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
     Context* context)
-    : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+    : descriptor_(descriptor),
+      name_resolver_(context->GetNameResolver()),
+      context_(context) {
   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
                       context->GetFieldGeneratorInfo(descriptor),
-                      name_resolver_, &variables_);
+                      name_resolver_, &variables_, context);
 }
 
 ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {}
@@ -419,7 +424,7 @@
 
 void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -430,13 +435,14 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "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_,
       "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -860,7 +866,7 @@
     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
   SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
                       context->GetFieldGeneratorInfo(descriptor),
-                      name_resolver_, &variables_);
+                      name_resolver_, &variables_, context);
 }
 
 RepeatedImmutableMessageFieldGenerator::
@@ -1422,7 +1428,7 @@
       "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$ val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -1433,7 +1439,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"
@@ -1444,7 +1450,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"
@@ -1456,7 +1462,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"
@@ -1467,7 +1473,7 @@
                  "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1480,7 +1486,7 @@
       "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1492,7 +1498,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"
@@ -1508,4 +1514,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.h b/src/google/protobuf/compiler/java/message_field.h
index 32dd4f0..65ce373 100644
--- a/src/google/protobuf/compiler/java/message_field.h
+++ b/src/google/protobuf/compiler/java/message_field.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,10 @@
                                           int messageBitIndex,
                                           int builderBitIndex,
                                           Context* context);
+  ImmutableMessageFieldGenerator(const ImmutableMessageFieldGenerator&) =
+      delete;
+  ImmutableMessageFieldGenerator& operator=(
+      const ImmutableMessageFieldGenerator&) = delete;
   ~ImmutableMessageFieldGenerator() override;
 
   // implements ImmutableFieldGenerator
@@ -91,6 +95,7 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, std::string> variables_;
   ClassNameResolver* name_resolver_;
+  Context* context_;
 
   void PrintNestedBuilderCondition(io::Printer* printer,
                                    const char* regular_case,
@@ -102,7 +107,6 @@
                                   const char* trailing_code) const;
 
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator);
   void GenerateKotlinOrNull(io::Printer* printer) const;
 };
 
@@ -112,6 +116,10 @@
   ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor,
                                       int messageBitIndex, int builderBitIndex,
                                       Context* context);
+  ImmutableMessageOneofFieldGenerator(
+      const ImmutableMessageOneofFieldGenerator&) = delete;
+  ImmutableMessageOneofFieldGenerator& operator=(
+      const ImmutableMessageOneofFieldGenerator&) = delete;
   ~ImmutableMessageOneofFieldGenerator() override;
 
   void GenerateMembers(io::Printer* printer) const override;
@@ -121,9 +129,6 @@
   void GenerateParsingCode(io::Printer* printer) const override;
   void GenerateSerializationCode(io::Printer* printer) const override;
   void GenerateSerializedSizeCode(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator);
 };
 
 class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator {
@@ -131,6 +136,10 @@
   explicit RepeatedImmutableMessageFieldGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex,
       int builderBitIndex, Context* context);
+  RepeatedImmutableMessageFieldGenerator(
+      const RepeatedImmutableMessageFieldGenerator&) = delete;
+  RepeatedImmutableMessageFieldGenerator& operator=(
+      const RepeatedImmutableMessageFieldGenerator&) = delete;
   ~RepeatedImmutableMessageFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
@@ -168,9 +177,6 @@
                                   const char* regular_case,
                                   const char* nested_builder_case,
                                   const char* trailing_code) const;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/message_field_lite.cc b/src/google/protobuf/compiler/java/message_field_lite.cc
index eb37ca6..ad685eb 100644
--- a/src/google/protobuf/compiler/java/message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/message_field_lite.cc
@@ -32,22 +32,23 @@
 //  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 "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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -59,12 +60,13 @@
 void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
                          int builderBitIndex, const FieldGeneratorInfo* info,
                          ClassNameResolver* name_resolver,
-                         std::map<std::string, std::string>* variables) {
+                         std::map<std::string, std::string>* variables,
+                         Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
-  (*variables)["kt_type"] = (*variables)["type"];
+  (*variables)["kt_type"] = EscapeKotlinKeywords((*variables)["type"]);
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->message_type());
   (*variables)["group_or_message"] =
@@ -118,10 +120,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() {}
@@ -288,7 +291,7 @@
 
 void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -299,13 +302,14 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "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_,
       "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -495,10 +499,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::
@@ -528,6 +534,13 @@
 
 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 +822,7 @@
       "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$ val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -820,7 +833,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 +844,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 +856,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 +867,7 @@
                  "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -867,7 +880,7 @@
       "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -879,7 +892,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 +908,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..c5387a6 100644
--- a/src/google/protobuf/compiler/java/message_field_lite.h
+++ b/src/google/protobuf/compiler/java/message_field_lite.h
@@ -39,7 +39,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,10 @@
   explicit ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor,
                                               int messageBitIndex,
                                               Context* context);
+  ImmutableMessageFieldLiteGenerator(
+      const ImmutableMessageFieldLiteGenerator&) = delete;
+  ImmutableMessageFieldLiteGenerator& operator=(
+      const ImmutableMessageFieldLiteGenerator&) = delete;
   ~ImmutableMessageFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
@@ -82,9 +86,9 @@
   std::map<std::string, 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 +98,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 +109,6 @@
   void GenerateFieldInfo(io::Printer* printer,
                          std::vector<uint16_t>* output) const override;
 
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
 };
 
 class RepeatedImmutableMessageFieldLiteGenerator
@@ -110,6 +116,10 @@
  public:
   explicit RepeatedImmutableMessageFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  RepeatedImmutableMessageFieldLiteGenerator(
+      const RepeatedImmutableMessageFieldLiteGenerator&) = delete;
+  RepeatedImmutableMessageFieldLiteGenerator& operator=(
+      const RepeatedImmutableMessageFieldLiteGenerator&) = delete;
   ~RepeatedImmutableMessageFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
@@ -128,9 +138,7 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, 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 a42ae3f..fc98ef5 100644
--- a/src/google/protobuf/compiler/java/message_lite.cc
+++ b/src/google/protobuf/compiler/java/message_lite.cc
@@ -32,7 +32,7 @@
 //  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>
@@ -40,24 +40,26 @@
 #include <memory>
 #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 "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 "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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -114,6 +116,10 @@
 void ImmutableMessageLiteGenerator::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"
@@ -184,7 +190,7 @@
         "      $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 {
@@ -235,44 +241,50 @@
     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->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->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,7 +296,7 @@
         "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()
@@ -307,7 +319,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()));
     field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
     printer->Print("\n");
   }
@@ -747,7 +759,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();
 
@@ -768,7 +781,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 +794,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"
       "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("object $name$Kt {\n", "name", descriptor_->name());
   printer->Indent();
   GenerateKotlinDsl(printer);
@@ -806,14 +828,19 @@
 
 void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers(
     io::Printer* printer) const {
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.errorprone.annotations.CheckReturnValue\n");
+  }
   printer->Print(
       "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 +860,21 @@
           "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"
@@ -1000,4 +1030,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/stubs/statusor.cc b/src/google/protobuf/compiler/java/message_serialization.cc
similarity index 76%
copy from src/google/protobuf/stubs/statusor.cc
copy to src/google/protobuf/compiler/java/message_serialization.cc
index 9c0a178..d0a0fe2 100644
--- a/src/google/protobuf/stubs/statusor.cc
+++ b/src/google/protobuf/compiler/java/message_serialization.cc
@@ -28,21 +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/stubs/statusor.h>
+#include "google/protobuf/compiler/java/message_serialization.h"
 
-#include <google/protobuf/stubs/logging.h>
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/descriptor.h"
+#include "absl/strings/str_cat.h"
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace statusor_internal {
+namespace compiler {
+namespace java {
 
-void StatusOrHelper::Crash(const Status& status) {
-  GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
-                    << status.ToString();
+void GenerateSerializeExtensionRange(io::Printer* printer,
+                                     const Descriptor::ExtensionRange* range) {
+  printer->Print("extensionWriter.writeUntil($end$, output);\n", "end",
+                 absl::StrCat(range->end));
 }
 
-}  // namespace statusor_internal
-}  // 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..3b11c47
--- /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/io/printer.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/java/field.h"
+#include "google/protobuf/compiler/java/helpers.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..84e74ff 100644
--- a/src/google/protobuf/compiler/java/name_resolver.cc
+++ b/src/google/protobuf/compiler/java/name_resolver.cc
@@ -28,18 +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/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 "google/protobuf/compiler/code_generator.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/substitute.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 +111,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 +144,6 @@
 
 }  // namespace
 
-ClassNameResolver::ClassNameResolver() {}
-
-ClassNameResolver::~ClassNameResolver() {}
-
 std::string ClassNameResolver::GetFileDefaultImmutableClassName(
     const FileDescriptor* file) {
   std::string basename;
@@ -217,8 +216,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 +231,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 +251,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 +311,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 +375,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 +385,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..d73b355 100644
--- a/src/google/protobuf/compiler/java/name_resolver.h
+++ b/src/google/protobuf/compiler/java/name_resolver.h
@@ -34,10 +34,13 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.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,
@@ -145,8 +153,6 @@
   // Caches the result to provide better performance.
   std::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.h b/src/google/protobuf/compiler/java/names.h
index 313ace4..f9c4b95 100644
--- a/src/google/protobuf/compiler/java/names.h
+++ b/src/google/protobuf/compiler/java/names.h
@@ -40,6 +40,8 @@
 
 #include <string>
 
+#include "google/protobuf/compiler/java/options.h"
+
 namespace google {
 namespace protobuf {
 
@@ -85,7 +87,8 @@
 //
 // Returns:
 //   Java package name.
-std::string FileJavaPackage(const FileDescriptor* descriptor);
+std::string FileJavaPackage(const FileDescriptor* descriptor,
+                            Options options = {});
 
 // Requires:
 //   descriptor != NULL
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..7fcfd87 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/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/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "absl/strings/str_split.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 9ec99f9..3706ef1 100644
--- a/src/google/protobuf/compiler/java/primitive_field.cc
+++ b/src/google/protobuf/compiler/java/primitive_field.cc
@@ -32,21 +32,22 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/primitive_field.h>
+#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 <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 "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"
 
 namespace google {
 namespace protobuf {
@@ -61,7 +62,8 @@
                            int messageBitIndex, int builderBitIndex,
                            const FieldGeneratorInfo* info,
                            ClassNameResolver* name_resolver,
-                           std::map<std::string, std::string>* variables) {
+                           std::map<std::string, std::string>* variables,
+                           Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
   JavaType javaType = GetJavaType(descriptor);
 
@@ -106,16 +108,18 @@
     (*variables)["repeated_set"] = (*variables)["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"] =
@@ -136,7 +140,7 @@
           : "";
   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();";
 
@@ -209,7 +213,7 @@
     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
@@ -318,7 +322,7 @@
 
 void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -329,14 +333,15 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "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_,
         "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -680,7 +685,7 @@
     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 RepeatedImmutablePrimitiveFieldGenerator::
@@ -852,7 +857,7 @@
       "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$ val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -863,7 +868,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"
@@ -874,7 +879,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"
@@ -886,7 +891,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"
@@ -897,7 +902,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -910,7 +915,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -922,7 +927,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 f8ffc56..914772c 100644
--- a/src/google/protobuf/compiler/java/primitive_field.h
+++ b/src/google/protobuf/compiler/java/primitive_field.h
@@ -38,7 +38,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,10 @@
                                             int messageBitIndex,
                                             int builderBitIndex,
                                             Context* context);
+  ImmutablePrimitiveFieldGenerator(const ImmutablePrimitiveFieldGenerator&) =
+      delete;
+  ImmutablePrimitiveFieldGenerator& operator=(
+      const ImmutablePrimitiveFieldGenerator&) = delete;
   ~ImmutablePrimitiveFieldGenerator() override;
 
   // implements ImmutableFieldGenerator
@@ -91,9 +95,6 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, std::string> variables_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator);
 };
 
 class ImmutablePrimitiveOneofFieldGenerator
@@ -102,6 +103,10 @@
   ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
                                         int messageBitIndex,
                                         int builderBitIndex, Context* context);
+  ImmutablePrimitiveOneofFieldGenerator(
+      const ImmutablePrimitiveOneofFieldGenerator&) = delete;
+  ImmutablePrimitiveOneofFieldGenerator& operator=(
+      const ImmutablePrimitiveOneofFieldGenerator&) = delete;
   ~ImmutablePrimitiveOneofFieldGenerator() override;
 
   void GenerateMembers(io::Printer* printer) const override;
@@ -111,9 +116,6 @@
   void GenerateParsingCode(io::Printer* printer) const override;
   void GenerateSerializationCode(io::Printer* printer) const override;
   void GenerateSerializedSizeCode(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator);
 };
 
 class RepeatedImmutablePrimitiveFieldGenerator
@@ -122,6 +124,10 @@
   explicit RepeatedImmutablePrimitiveFieldGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex,
       int builderBitIndex, Context* context);
+  RepeatedImmutablePrimitiveFieldGenerator(
+      const RepeatedImmutablePrimitiveFieldGenerator&) = delete;
+  RepeatedImmutablePrimitiveFieldGenerator& operator=(
+      const RepeatedImmutablePrimitiveFieldGenerator&) = delete;
   ~RepeatedImmutablePrimitiveFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
@@ -151,8 +157,6 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, std::string> variables_;
   ClassNameResolver* name_resolver_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/primitive_field_lite.cc b/src/google/protobuf/compiler/java/primitive_field_lite.cc
index e323fef..28066bb 100644
--- a/src/google/protobuf/compiler/java/primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/primitive_field_lite.cc
@@ -32,21 +32,23 @@
 //  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 "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/stubs/strutil.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"
 
 namespace google {
 namespace protobuf {
@@ -69,19 +71,21 @@
                            int messageBitIndex, int builderBitIndex,
                            const FieldGeneratorInfo* info,
                            ClassNameResolver* name_resolver,
-                           std::map<std::string, std::string>* variables) {
+                           std::map<std::string, 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)["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";
 
@@ -123,7 +127,7 @@
 
   if (javaType == JAVATYPE_BYTES) {
     (*variables)["bytes_default"] =
-        ToUpper((*variables)["name"]) + "_DEFAULT_VALUE";
+        absl::AsciiStrToUpper((*variables)["name"]) + "_DEFAULT_VALUE";
   }
 
   if (IsReferenceType(javaType)) {
@@ -145,7 +149,7 @@
           : "";
   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)) {
@@ -199,10 +203,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() {}
@@ -231,6 +236,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 +353,15 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "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_,
         "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -492,7 +512,7 @@
       name_resolver_(context->GetNameResolver()) {
   SetPrimitiveVariables(descriptor, messageBitIndex, 0,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 RepeatedImmutablePrimitiveFieldLiteGenerator::
@@ -685,7 +705,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 +716,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 +728,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 +739,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -732,7 +752,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -744,7 +764,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..410b7d6 100644
--- a/src/google/protobuf/compiler/java/primitive_field_lite.h
+++ b/src/google/protobuf/compiler/java/primitive_field_lite.h
@@ -39,7 +39,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,10 @@
  public:
   explicit ImmutablePrimitiveFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  ImmutablePrimitiveFieldLiteGenerator(
+      const ImmutablePrimitiveFieldLiteGenerator&) = delete;
+  ImmutablePrimitiveFieldLiteGenerator& operator=(
+      const ImmutablePrimitiveFieldLiteGenerator&) = delete;
   ~ImmutablePrimitiveFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
@@ -81,10 +85,8 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, std::string> variables_;
   const int messageBitIndex_;
+  Context* context_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator);
 };
 
 class ImmutablePrimitiveOneofFieldLiteGenerator
@@ -93,6 +95,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 +106,6 @@
 
   void GenerateFieldInfo(io::Printer* printer,
                          std::vector<uint16_t>* output) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
 };
 
 class RepeatedImmutablePrimitiveFieldLiteGenerator
@@ -110,6 +113,10 @@
  public:
   explicit RepeatedImmutablePrimitiveFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  RepeatedImmutablePrimitiveFieldLiteGenerator(
+      const RepeatedImmutablePrimitiveFieldLiteGenerator&) = delete;
+  RepeatedImmutablePrimitiveFieldLiteGenerator& operator=(
+      const RepeatedImmutablePrimitiveFieldLiteGenerator&) = delete;
   ~RepeatedImmutablePrimitiveFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
@@ -129,8 +136,6 @@
   std::map<std::string, 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..ab1d52c 100644
--- a/src/google/protobuf/compiler/java/service.cc
+++ b/src/google/protobuf/compiler/java/service.cc
@@ -32,17 +32,18 @@
 //  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 "google/protobuf/io/printer.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"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -68,6 +69,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 +97,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.
@@ -212,7 +217,7 @@
   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);
+    vars["index"] = absl::StrCat(i);
     vars["method"] = UnderscoresToCamelCase(method);
     vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
     vars["output"] = GetOutput(method);
@@ -259,7 +264,7 @@
   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);
+    vars["index"] = absl::StrCat(i);
     vars["method"] = UnderscoresToCamelCase(method);
     vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
     vars["output"] = GetOutput(method);
@@ -304,7 +309,7 @@
   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);
+    vars["index"] = absl::StrCat(i);
     vars["type"] =
         (which == REQUEST)
             ? name_resolver_->GetImmutableClassName(method->input_type())
@@ -359,7 +364,7 @@
     printer->Indent();
 
     std::map<std::string, std::string> vars;
-    vars["index"] = StrCat(i);
+    vars["index"] = absl::StrCat(i);
     vars["output"] = GetOutput(method);
     printer->Print(vars,
                    "channel.callMethod(\n"
@@ -423,7 +428,7 @@
     printer->Indent();
 
     std::map<std::string, std::string> vars;
-    vars["index"] = StrCat(i);
+    vars["index"] = absl::StrCat(i);
     vars["output"] = GetOutput(method);
     printer->Print(vars,
                    "return ($output$) channel.callBlockingMethod(\n"
@@ -476,4 +481,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..06f50ff 100644
--- a/src/google/protobuf/compiler/java/service.h
+++ b/src/google/protobuf/compiler/java/service.h
@@ -36,7 +36,7 @@
 #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 +60,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 +71,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 +130,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..c70b61c 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 "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 "absl/strings/escaping.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"
 
 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 3228da6..d8b5d4e 100644
--- a/src/google/protobuf/compiler/java/string_field.cc
+++ b/src/google/protobuf/compiler/java/string_field.cc
@@ -33,21 +33,22 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/string_field.h>
+#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 <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 "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"
 
 namespace google {
 namespace protobuf {
@@ -63,18 +64,21 @@
                            int messageBitIndex, int builderBitIndex,
                            const FieldGeneratorInfo* info,
                            ClassNameResolver* name_resolver,
-                           std::map<std::string, std::string>* variables) {
+                           std::map<std::string, 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) {\n"
@@ -151,7 +155,7 @@
     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
@@ -377,7 +381,7 @@
 
 void ImmutableStringFieldGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$var $kt_name$: kotlin.String\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -388,14 +392,15 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "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_,
         "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -752,7 +757,7 @@
     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
   SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 RepeatedImmutableStringFieldGenerator::
@@ -967,7 +972,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$ val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -979,7 +985,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"
@@ -991,7 +997,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"
@@ -1004,7 +1010,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"
@@ -1017,7 +1023,7 @@
 
   // List<String> += Iterable<String>
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1031,7 +1037,7 @@
 
   // List<String>[Int] = String
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1043,7 +1049,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 b38d8e1..b8bc921 100644
--- a/src/google/protobuf/compiler/java/string_field.h
+++ b/src/google/protobuf/compiler/java/string_field.h
@@ -39,7 +39,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,9 @@
   explicit ImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
                                          int messageBitIndex,
                                          int builderBitIndex, Context* context);
+  ImmutableStringFieldGenerator(const ImmutableStringFieldGenerator&) = delete;
+  ImmutableStringFieldGenerator& operator=(
+      const ImmutableStringFieldGenerator&) = delete;
   ~ImmutableStringFieldGenerator() override;
 
   // implements ImmutableFieldGenerator
@@ -91,9 +94,6 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, std::string> variables_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator);
 };
 
 class ImmutableStringOneofFieldGenerator
@@ -102,6 +102,10 @@
   ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor,
                                      int messageBitIndex, int builderBitIndex,
                                      Context* context);
+  ImmutableStringOneofFieldGenerator(
+      const ImmutableStringOneofFieldGenerator&) = delete;
+  ImmutableStringOneofFieldGenerator& operator=(
+      const ImmutableStringOneofFieldGenerator&) = delete;
   ~ImmutableStringOneofFieldGenerator() override;
 
  private:
@@ -112,8 +116,6 @@
   void GenerateParsingCode(io::Printer* printer) const override;
   void GenerateSerializationCode(io::Printer* printer) const override;
   void GenerateSerializedSizeCode(io::Printer* printer) const override;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator);
 };
 
 class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator {
@@ -121,6 +123,10 @@
   explicit RepeatedImmutableStringFieldGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex,
       int builderBitIndex, Context* context);
+  RepeatedImmutableStringFieldGenerator(
+      const RepeatedImmutableStringFieldGenerator&) = delete;
+  RepeatedImmutableStringFieldGenerator& operator=(
+      const RepeatedImmutableStringFieldGenerator&) = delete;
   ~RepeatedImmutableStringFieldGenerator() override;
 
   // implements ImmutableFieldGenerator ---------------------------------------
@@ -149,8 +155,6 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, std::string> variables_;
   ClassNameResolver* name_resolver_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/string_field_lite.cc b/src/google/protobuf/compiler/java/string_field_lite.cc
index 8e5b230..2551d39 100644
--- a/src/google/protobuf/compiler/java/string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/string_field_lite.cc
@@ -33,21 +33,22 @@
 //  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 "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"
 
 namespace google {
 namespace protobuf {
@@ -63,19 +64,22 @@
                            int messageBitIndex, int builderBitIndex,
                            const FieldGeneratorInfo* info,
                            ClassNameResolver* name_resolver,
-                           std::map<std::string, std::string>* variables) {
+                           std::map<std::string, 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.
@@ -92,8 +96,17 @@
                 " 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);
 
@@ -126,10 +139,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() {}
@@ -181,6 +195,21 @@
 
 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 +340,7 @@
 
 void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$var $kt_name$: kotlin.String\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -322,14 +351,15 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "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_,
         "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -519,10 +549,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::
@@ -553,6 +585,14 @@
 
 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 +792,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$ val $kt_name$: "
@@ -766,7 +807,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 +819,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 +832,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 +845,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 +859,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 +871,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..f35da28 100644
--- a/src/google/protobuf/compiler/java/string_field_lite.h
+++ b/src/google/protobuf/compiler/java/string_field_lite.h
@@ -40,7 +40,7 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +63,10 @@
   explicit ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
                                              int messageBitIndex,
                                              Context* context);
+  ImmutableStringFieldLiteGenerator(const ImmutableStringFieldLiteGenerator&) =
+      delete;
+  ImmutableStringFieldLiteGenerator& operator=(
+      const ImmutableStringFieldLiteGenerator&) = delete;
   ~ImmutableStringFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
@@ -83,9 +87,7 @@
   std::map<std::string, std::string> variables_;
   const int messageBitIndex_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldLiteGenerator);
+  Context* context_;
 };
 
 class ImmutableStringOneofFieldLiteGenerator
@@ -93,6 +95,10 @@
  public:
   ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
                                          int messageBitIndex, Context* context);
+  ImmutableStringOneofFieldLiteGenerator(
+      const ImmutableStringOneofFieldLiteGenerator&) = delete;
+  ImmutableStringOneofFieldLiteGenerator& operator=(
+      const ImmutableStringOneofFieldLiteGenerator&) = delete;
   ~ImmutableStringOneofFieldLiteGenerator() override;
 
  private:
@@ -100,8 +106,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 +113,10 @@
  public:
   explicit RepeatedImmutableStringFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  RepeatedImmutableStringFieldLiteGenerator(
+      const RepeatedImmutableStringFieldLiteGenerator&) = delete;
+  RepeatedImmutableStringFieldLiteGenerator& operator=(
+      const RepeatedImmutableStringFieldLiteGenerator&) = delete;
   ~RepeatedImmutableStringFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
@@ -127,8 +135,7 @@
   const FieldDescriptor* descriptor_;
   std::map<std::string, 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..ecaf76b 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/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"
 
 // 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..f19cbf5 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,24 @@
 #include <memory>
 #include <vector>
 
-#include <google/protobuf/stubs/strutil.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/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/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/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 +77,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 +112,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 +123,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);
@@ -251,10 +254,10 @@
 
   bool insert_endlines = HasPrefixString(parameter, "insert_endlines=");
   if (insert_endlines || HasPrefixString(parameter, "insert=")) {
-    std::vector<std::string> insert_into = Split(
+    std::vector<std::string> insert_into = absl::StrSplit(
         StripPrefixString(
             parameter, insert_endlines ? "insert_endlines=" : "insert="),
-        ",", true);
+        ",", absl::SkipEmpty());
 
     for (size_t i = 0; i < insert_into.size(); i++) {
       {
@@ -375,7 +378,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..d1cb460
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/BUILD.bazel
@@ -0,0 +1,82 @@
+################################################################################
+# 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 = "objectivec",
+    srcs = [
+        "objectivec_enum.cc",
+        "objectivec_enum_field.cc",
+        "objectivec_extension.cc",
+        "objectivec_field.cc",
+        "objectivec_file.cc",
+        "objectivec_generator.cc",
+        "objectivec_helpers.cc",
+        "objectivec_map_field.cc",
+        "objectivec_message.cc",
+        "objectivec_message_field.cc",
+        "objectivec_oneof.cc",
+        "objectivec_primitive_field.cc",
+    ],
+    hdrs = [
+        "objectivec_enum.h",
+        "objectivec_enum_field.h",
+        "objectivec_extension.h",
+        "objectivec_field.h",
+        "objectivec_file.h",
+        "objectivec_generator.h",
+        "objectivec_helpers.h",
+        "objectivec_map_field.h",
+        "objectivec_message.h",
+        "objectivec_message_field.h",
+        "objectivec_nsobject_methods.h",
+        "objectivec_oneof.h",
+        "objectivec_primitive_field.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/objectivec",
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/compiler:__pkg__",
+    ],
+    deps = [
+        "//:protobuf",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_test(
+    name = "helpers_unittest",
+    srcs = ["objectivec_helpers_unittest.cc"],
+    deps = [
+        ":objectivec",
+        "//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/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
index ea8f394..7e1283b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -31,16 +31,35 @@
 #include <map>
 #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 "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 "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
 #include <algorithm> // std::find()
 
 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),
@@ -128,7 +147,7 @@
       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");
@@ -141,7 +160,7 @@
         "$name$$deprecated_attribute$ = $value$,\n",
         "name", EnumValueName(all_values_[i]),
         "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]),
-        "value", StrCat(all_values_[i]->number()));
+        "value", SafelyPrintIntToCode(all_values_[i]->number()));
   }
   printer->Outdent();
   printer->Print(
@@ -195,7 +214,7 @@
   for (int i = 0; i < text_blob.size(); i += kBytesPerLine) {
     printer->Print(
         "\n        \"$data$\"",
-        "data", EscapeTrigraphs(CEscape(text_blob.substr(i, kBytesPerLine))));
+        "data", EscapeTrigraphs(absl::CEscape(text_blob.substr(i, kBytesPerLine))));
   }
   printer->Print(
       ";\n"
@@ -225,7 +244,7 @@
         "                                     enumVerifier:$name$_IsValidValue\n"
         "                              extraTextFormatInfo:extraTextFormatInfo];\n",
         "name", name_,
-        "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
+        "extraTextFormatInfo", absl::CEscape(text_format_decode_data.Data()));
     }
     printer->Print(
       "    GPBEnumDescriptor *expected = nil;\n"
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
index 1d5741a..0759ae5 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
@@ -34,8 +34,8 @@
 #include <string>
 #include <set>
 #include <vector>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
index 6e0d69b..049ff47 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -31,9 +31,9 @@
 #include <map>
 #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 "google/protobuf/compiler/objectivec/objectivec_enum_field.h"
+#include "google/protobuf/compiler/objectivec/objectivec_helpers.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
index f0d685c..7bd3c32 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -33,7 +33,7 @@
 
 #include <map>
 #include <string>
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include "google/protobuf/compiler/objectivec/objectivec_field.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
index 9cebcb2..c70766a 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -30,11 +30,19 @@
 
 #include <iostream>
 
-#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 "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 "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -86,7 +94,7 @@
   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");
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
index d412f4a..cfdf718 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
@@ -31,8 +31,8 @@
 #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 "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index 004ea19..f11cbde 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -30,14 +30,22 @@
 
 #include <iostream>
 
-#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 "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 "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
 
 namespace google {
 namespace protobuf {
@@ -74,7 +82,7 @@
   (*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);
   std::vector<std::string> field_flags;
@@ -224,7 +232,7 @@
 }
 
 void FieldGenerator::SetRuntimeHasBit(int has_index) {
-  variables_["has_index"] = StrCat(has_index);
+  variables_["has_index"] = absl::StrCat(has_index);
 }
 
 void FieldGenerator::SetNoHasBit(void) {
@@ -248,7 +256,7 @@
   if (oneof != NULL) {
     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);
   }
 }
 
@@ -388,7 +396,7 @@
       "$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");
   if (IsInitName(variables_.find("name")->second)) {
     // If property name starts with init we need to annotate it to get past ARC.
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
index 759ef80..6750b51 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -33,8 +33,8 @@
 
 #include <map>
 #include <string>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index 50b4285..a420c2c 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.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/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 "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 "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
 #include <algorithm> // std::find()
 #include <iostream>
 #include <sstream>
@@ -145,9 +153,9 @@
     return it->second;
   }
 
-  std::set<const FileDescriptor*> min_deps_collector;
-  std::set<const FileDescriptor*> covered_deps_collector;
-  std::set<const FileDescriptor*> to_prune;
+  std::unordered_set<const FileDescriptor*> min_deps_collector;
+  std::unordered_set<const FileDescriptor*> covered_deps_collector;
+  std::unordered_set<const FileDescriptor*> to_prune;
   for (int i = 0; i < file->dependency_count(); i++) {
     const FileDescriptor* dep = file->dependency(i);
     MinDepsEntry dep_info =
@@ -180,7 +188,7 @@
         {file, {file_has_exts, min_deps_collector, covered_deps_collector}}).first->second;
   }
 
-  std::set<const FileDescriptor*> min_deps;
+  std::unordered_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){
@@ -202,7 +210,7 @@
 const std::vector<const FileDescriptor*>
 FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensions(
     const FileDescriptor* file) {
-  std::set<const FileDescriptor*> min_deps =
+  std::unordered_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());
@@ -267,7 +275,7 @@
       "#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));
+      "google_protobuf_objc_version", absl::StrCat(GOOGLE_PROTOBUF_OBJC_VERSION));
 
   // The bundled protos (WKTs) don't use of forward declarations.
   bool headers_use_forward_declarations =
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
index ef49cf8..842ddff 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -31,12 +31,12 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
 
-#include <map>
-#include <set>
 #include <string>
+#include <unordered_map>
+#include <unordered_set>
 #include <vector>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -71,13 +71,13 @@
    private:
     struct MinDepsEntry {
       bool has_extensions;
-      std::set<const FileDescriptor*> min_deps;
+      std::unordered_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;
+      std::unordered_set<const FileDescriptor*> covered_deps;
     };
     const MinDepsEntry& CollectMinimalFileDepsContainingExtensionsInternal(const FileDescriptor* file);
-    std::map<const FileDescriptor*, MinDepsEntry> deps_info_cache_;
+    std::unordered_map<const FileDescriptor*, MinDepsEntry> deps_info_cache_;
   };
 
   FileGenerator(const FileDescriptor* file,
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
index 9dccf14..e2efe29 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -32,12 +32,20 @@
 #include <iostream>
 #include <string>
 #include <unordered_set>
-#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
-#include <google/protobuf/compiler/objectivec/objectivec_file.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/strutil.h>
+#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 "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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;
@@ -122,8 +130,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));
       }
@@ -230,6 +238,10 @@
       //   - 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)) {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
index 1dbc666..f863fc8 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
@@ -34,10 +34,10 @@
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
 
 #include <string>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -74,6 +74,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/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index b15f580..1dbff83 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -41,17 +41,21 @@
 #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>
+#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"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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.
@@ -65,28 +69,28 @@
 // in this port namespace to avoid ambiguous definition.
 namespace posix {
 #ifdef _WIN32
-using ::google::protobuf::io::win32::open;
-#else
+using google::protobuf::io::win32::open;
+#else  // !_WIN32
 using ::open;
-#endif
-}  // namespace port
+#endif  // _WIN32
+}  // namespace posix
 
 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 std::string("YES") == absl::AsciiStrToUpper(value);
   }
   return default_value;
 }
 
 class SimpleLineCollector : public LineConsumer {
  public:
-  SimpleLineCollector(std::unordered_set<std::string>* inout_set)
+  explicit SimpleLineCollector(std::unordered_set<std::string>* inout_set)
       : set_(inout_set) {}
 
-  virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override {
+  virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) override {
     set_->insert(std::string(line));
     return true;
   }
@@ -101,7 +105,7 @@
                              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;
+  virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) override;
 
  private:
   const std::string usage_;
@@ -112,7 +116,7 @@
  public:
   PrefixModeStorage();
 
-  const std::string package_to_prefix_mappings_path() const { return package_to_prefix_mappings_path_; }
+  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();
@@ -123,7 +127,7 @@
   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_; }
+  std::string exception_path() const { return exception_path_; }
   void set_exception_path(const std::string& path) {
     exception_path_ = path;
     exceptions_.clear();
@@ -134,6 +138,7 @@
   // 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_;
@@ -155,8 +160,6 @@
     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;
@@ -254,6 +257,14 @@
   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);
+}
+
 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
@@ -265,7 +276,7 @@
   const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS");
   if (suppressions) {
     expected_prefixes_suppressions =
-        Split(suppressions, ";", true);
+        absl::StrSplit(suppressions, ";", absl::SkipEmpty());
   }
   prefixes_must_be_registered =
       BoolFromEnvVar("GPB_OBJC_PREFIXES_MUST_BE_REGISTERED", false);
@@ -286,7 +297,7 @@
 const char* const kUpperSegmentsList[] = {"url", "http", "https"};
 
 std::unordered_set<std::string> kUpperSegments =
-    MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
+    MakeWordsMap(kUpperSegmentsList, ABSL_ARRAYSIZE(kUpperSegmentsList));
 
 bool ascii_isnewline(char c) {
   return c == '\n' || c == '\r';
@@ -305,7 +316,7 @@
   bool last_char_was_upper = false;
   for (int i = 0; i < input.size(); i++) {
     char c = input[i];
-    if (ascii_isdigit(c)) {
+    if (absl::ascii_isdigit(c)) {
       if (!last_char_was_number) {
         values.push_back(current);
         current = "";
@@ -313,7 +324,7 @@
       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)) {
+    } 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);
@@ -322,12 +333,12 @@
       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)) {
+    } else if (absl::ascii_isupper(c)) {
       if (!last_char_was_upper) {
         values.push_back(current);
         current = "";
       }
-      current += ascii_tolower(c);
+      current += absl::ascii_tolower(c);
       last_char_was_number = last_char_was_lower = last_char_was_upper = false;
       last_char_was_upper = true;
     } else {
@@ -347,7 +358,7 @@
     }
     for (int j = 0; j < value.length(); j++) {
       if (j == 0 || all_upper) {
-        value[j] = ascii_toupper(value[j]);
+        value[j] = absl::ascii_toupper(value[j]);
       } else {
         // Nothing, already in lower.
       }
@@ -357,7 +368,7 @@
   if ((result.length() != 0) &&
       !first_capitalized &&
       !first_segment_forces_upper) {
-    result[0] = ascii_tolower(result[0]);
+    result[0] = absl::ascii_tolower(result[0]);
   }
   return result;
 }
@@ -446,9 +457,9 @@
                                 const std::string& extension,
                                 std::string* out_suffix_added) {
   static const std::unordered_set<std::string> kReservedWords =
-      MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
+      MakeWordsMap(kReservedWordList, ABSL_ARRAYSIZE(kReservedWordList));
   static const std::unordered_set<std::string> kNSObjectMethods =
-      MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList));
+      MakeWordsMap(kNSObjectMethodsList, ABSL_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':
@@ -456,7 +467,7 @@
   // 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()])) {
+    if (input.length() == prefix.length() || !absl::ascii_isupper(input[prefix.length()])) {
       sanitized = prefix + input;
     } else {
       sanitized = input;
@@ -511,7 +522,7 @@
         // 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]);
+        return !absl::ascii_islower(name[length]);
       } else {
         return true;
       }
@@ -548,7 +559,7 @@
   }
 }
 
-void MaybeUnQuote(StringPiece* input) {
+void MaybeUnQuote(absl::string_view* input) {
   if ((input->length() >= 2) &&
       ((*input->data() == '\'' || *input->data() == '"')) &&
       ((*input)[input->length() - 1] == *input->data())) {
@@ -560,15 +571,15 @@
 }  // namespace
 
 // 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, {{"?", "\\?"}});
 }
 
-void TrimWhitespace(StringPiece* input) {
-  while (!input->empty() && ascii_isspace(*input->data())) {
+void TrimWhitespace(absl::string_view* input) {
+  while (!input->empty() && absl::ascii_isspace(*input->data())) {
     input->remove_prefix(1);
   }
-  while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) {
+  while (!input->empty() && absl::ascii_isspace((*input)[input->length() - 1])) {
     input->remove_suffix(1);
   }
 }
@@ -620,7 +631,7 @@
   // 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);
+  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()) {
@@ -760,10 +771,10 @@
   std::string result;
   for (int i = 0; i < name.size(); i++) {
     char c = name[i];
-    if (i > 0 && ascii_isupper(c)) {
+    if (i > 0 && absl::ascii_isupper(c)) {
       result += '_';
     }
-    result += ascii_toupper(c);
+    result += absl::ascii_toupper(c);
   }
   return result;
 }
@@ -794,7 +805,7 @@
   // name.
   std::string result = FieldName(field);
   if (result.length() > 0) {
-    result[0] = ascii_toupper(result[0]);
+    result[0] = absl::ascii_toupper(result[0]);
   }
   return result;
 }
@@ -818,7 +829,7 @@
   // 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]);
+    result[0] = absl::ascii_toupper(result[0]);
   }
   return result;
 }
@@ -841,8 +852,8 @@
   }
   if (field->type() == FieldDescriptor::TYPE_GROUP) {
     if (worker.length() > 0) {
-      if (ascii_islower(worker[0])) {
-        worker[0] = ascii_toupper(worker[0]);
+      if (absl::ascii_islower(worker[0])) {
+        worker[0] = absl::ascii_toupper(worker[0]);
       }
     }
     return worker;
@@ -850,11 +861,11 @@
     std::string result;
     for (int i = 0; i < worker.size(); i++) {
       char c = worker[i];
-      if (ascii_isupper(c)) {
+      if (absl::ascii_isupper(c)) {
         if (i > 0) {
           result += '_';
         }
-        result += ascii_tolower(c);
+        result += absl::ascii_tolower(c);
       } else {
         result += c;
       }
@@ -990,9 +1001,9 @@
     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)) {
+    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;
@@ -1053,17 +1064,17 @@
       if (field->default_value_int32() == INT_MIN) {
         return "-0x80000000";
       }
-      return StrCat(field->default_value_int32());
+      return absl::StrCat(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:
       // 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";
+      return absl::StrCat(field->default_value_int64()) + "LL";
     case FieldDescriptor::CPPTYPE_UINT64:
-      return StrCat(field->default_value_uint64()) + "ULL";
+      return absl::StrCat(field->default_value_uint64()) + "ULL";
     case FieldDescriptor::CPPTYPE_DOUBLE:
       return HandleExtremeFloatingPoint(
           SimpleDtoa(field->default_value_double()), false);
@@ -1093,9 +1104,9 @@
         uint32_t length = ghtonl(default_string.length());
         std::string bytes((const char*)&length, sizeof(length));
         bytes.append(default_string);
-        return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
+        return "(NSData*)\"" + EscapeTrigraphs(absl::CEscape(bytes)) + "\"";
       } else {
-        return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
+        return "@\"" + EscapeTrigraphs(absl::CEscape(default_string)) + "\"";
       }
     }
     case FieldDescriptor::CPPTYPE_ENUM:
@@ -1179,7 +1190,7 @@
                                ? location.trailing_comments
                                : location.leading_comments;
   std::vector<std::string> lines;
-  lines = Split(comments, "\n", false);
+  lines = absl::StrSplit(comments, "\n", absl::AllowEmpty());
   while (!lines.empty() && lines.back().empty()) {
     lines.pop_back();
   }
@@ -1206,14 +1217,15 @@
     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);
+  for (size_t i = 0; i < lines.size(); i++) {
+    std::string line = absl::StrReplaceAll(
+        StripPrefixString(lines[i], " "),
+        {// HeaderDoc and appledoc use '\' and '@' for markers; escape them.
+         {"\\", "\\\\"},
+         {"@", "\\@"},
+         // Decouple / from * to not have inline comments inside comments.
+         {"/*", "/\\*"},
+         {"*/", "*\\/"}});
     line = prefix + line;
     StripWhitespace(&line);
     // If not a one line, need to add the first space before *, as
@@ -1234,7 +1246,7 @@
 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 += absl::AsciiStrToUpper(framework_name);
   result += "_FRAMEWORK_IMPORTS";
   return result;
 }
@@ -1259,21 +1271,21 @@
   return false;
 }
 
-bool ReadLine(StringPiece* input, StringPiece* line) {
+bool ReadLine(absl::string_view* input, absl::string_view* line) {
   for (int len = 0; len < input->size(); ++len) {
     if (ascii_isnewline((*input)[len])) {
-      *line = StringPiece(input->data(), len);
+      *line = absl::string_view(input->data(), len);
       ++len;  // advance over the newline
-      *input = StringPiece(input->data() + len, input->size() - len);
+      *input = absl::string_view(input->data() + len, input->size() - len);
       return true;
     }
   }
   return false;  // Ran out of input with no newline.
 }
 
-void RemoveComment(StringPiece* input) {
+void RemoveComment(absl::string_view* input) {
   int offset = input->find('#');
-  if (offset != StringPiece::npos) {
+  if (offset != absl::string_view::npos) {
     input->remove_suffix(input->length() - offset);
   }
 }
@@ -1281,14 +1293,14 @@
 namespace {
 
 bool PackageToPrefixesCollector::ConsumeLine(
-    const StringPiece& line, std::string* out_error) {
+    const absl::string_view& line, std::string* out_error) {
   int offset = line.find('=');
-  if (offset == StringPiece::npos) {
-    *out_error = usage_ + " file line without equal sign: '" + StrCat(line) + "'.";
+  if (offset == absl::string_view::npos) {
+    *out_error = usage_ + " file line without equal sign: '" + absl::StrCat(line) + "'.";
     return false;
   }
-  StringPiece package = line.substr(0, offset);
-  StringPiece prefix = line.substr(offset + 1);
+  absl::string_view package = line.substr(0, offset);
+  absl::string_view prefix = line.substr(offset + 1);
   TrimWhitespace(&package);
   TrimWhitespace(&prefix);
   MaybeUnQuote(&prefix);
@@ -1410,7 +1422,7 @@
   // 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])) {
+  if (!prefix.empty() && !absl::ascii_isupper(prefix[0])) {
     std::cerr
          << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
@@ -1573,7 +1585,7 @@
 
   void AddChar(const char desired) {
     ++segment_len_;
-    is_all_upper_ &= ascii_isupper(desired);
+    is_all_upper_ &= absl::ascii_isupper(desired);
   }
 
   void Push() {
@@ -1588,9 +1600,9 @@
   bool AddFirst(const char desired, const char input) {
     if (desired == input) {
       op_ = kOpAsIs;
-    } else if (desired == ascii_toupper(input)) {
+    } else if (desired == absl::ascii_toupper(input)) {
       op_ = kOpFirstUpper;
-    } else if (desired == ascii_tolower(input)) {
+    } else if (desired == absl::ascii_tolower(input)) {
       op_ = kOpFirstLower;
     } else {
       // Can't be transformed to match.
@@ -1628,7 +1640,7 @@
   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)) {
+    if ((op_ != kOpAllUpper) || absl::ascii_isupper(desired)) {
       AddChar(desired);
       return true;
     }
@@ -1640,7 +1652,7 @@
 
   // If we need to uppercase, and everything so far has been uppercase,
   // promote op to AllUpper.
-  if ((desired == ascii_toupper(input)) && is_all_upper_) {
+  if ((desired == absl::ascii_toupper(input)) && is_all_upper_) {
     op_ = kOpAllUpper;
     AddChar(desired);
     return true;
@@ -1676,8 +1688,8 @@
   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;
+         << " input: \"" << absl::CEscape(input_for_decode) << "\", desired: \""
+         << absl::CEscape(desired_output) << "\"." << std::endl;
     std::cerr.flush();
     abort();
   }
@@ -1723,7 +1735,7 @@
 
   // 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);
+  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
@@ -1738,16 +1750,16 @@
   std::string leftover_;
 };
 
-bool Parser::ParseChunk(StringPiece chunk, std::string* out_error) {
-  StringPiece full_chunk;
+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 = StringPiece(leftover_);
+    full_chunk = absl::string_view(leftover_);
   } else {
     full_chunk = chunk;
   }
 
-  StringPiece line;
+  absl::string_view line;
   while (ReadLine(&full_chunk, &line)) {
     ++line_;
     RemoveComment(&line);
@@ -1783,7 +1795,7 @@
 }
 
 std::string FullErrorString(const std::string& name, int line_num, const std::string& msg) {
-  return std::string("error: ") + name + " Line " + StrCat(line_num) + ", " + msg;
+  return std::string("error: ") + name + " Line " + absl::StrCat(line_num) + ", " + msg;
 }
 
 }  // namespace
@@ -1822,7 +1834,7 @@
       continue;
     }
 
-    if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len),
+    if (!parser.ParseChunk(absl::string_view(static_cast<const char*>(buf), buf_len),
                            &local_error)) {
       *out_error = FullErrorString(stream_name, parser.last_line(), local_error);
       return false;
@@ -1989,26 +2001,26 @@
 }
 
 bool ImportWriter::ProtoFrameworkCollector::ConsumeLine(
-    const StringPiece& line, std::string* out_error) {
+    const absl::string_view& line, std::string* out_error) {
   int offset = line.find(':');
-  if (offset == StringPiece::npos) {
+  if (offset == absl::string_view::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);
+  absl::string_view framework_name = line.substr(0, offset);
+  absl::string_view 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) {
+    if (offset == absl::string_view::npos) {
       offset = proto_file_list.length();
     }
 
-    StringPiece proto_file = proto_file_list.substr(start, offset - start);
+    absl::string_view 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 =
@@ -2021,7 +2033,7 @@
         std::cerr.flush();
       }
 
-      if (proto_file.find(' ') != StringPiece::npos) {
+      if (proto_file.find(' ') != absl::string_view::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;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index d21fed2..9cee305 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -36,11 +36,11 @@
 #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/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +63,10 @@
 std::string PROTOC_EXPORT GetProtoPackagePrefixExceptionList();
 void PROTOC_EXPORT 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.
+std::string PROTOC_EXPORT GetForcedPackagePrefix();
+void PROTOC_EXPORT SetForcedPackagePrefix(const std::string& prefix);
 
 // Generator Prefix Validation Options (see objectivec_generator.cc for a
 // description of each):
@@ -75,10 +79,10 @@
 };
 
 // Escape C++ trigraphs by escaping question marks to "\?".
-std::string PROTOC_EXPORT EscapeTrigraphs(const std::string& to_escape);
+std::string PROTOC_EXPORT EscapeTrigraphs(absl::string_view to_escape);
 
-// Remove white space from either end of a StringPiece.
-void PROTOC_EXPORT TrimWhitespace(StringPiece* input);
+// Remove white space from either end of a absl::string_view.
+void PROTOC_EXPORT TrimWhitespace(absl::string_view* input);
 
 // Returns true if the name requires a ns_returns_not_retained attribute applied
 // to it.
@@ -287,7 +291,7 @@
  public:
   LineConsumer();
   virtual ~LineConsumer();
-  virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) = 0;
+  virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) = 0;
 };
 
 bool PROTOC_EXPORT ParseSimpleFile(const std::string& path,
@@ -323,7 +327,7 @@
     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;
+    virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) override;
 
    private:
     std::map<std::string, std::string>* map_;
@@ -348,6 +352,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
index 7ae6a92..7ad11f0 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_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/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include "google/protobuf/compiler/objectivec/objectivec_helpers.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 #include <gtest/gtest.h>
 
 namespace google {
@@ -244,12 +244,12 @@
 
 class TestLineCollector : public LineConsumer {
  public:
-  TestLineCollector(std::vector<std::string>* inout_lines,
+  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(const StringPiece& line, std::string* out_error) override {
+  bool ConsumeLine(const absl::string_view& line, std::string* out_error) override {
     if (reject_ && *reject_ == line) {
       if (!skip_msg_) {
         *out_error = std::string("Rejected '") + *reject_ + "'";
@@ -269,7 +269,7 @@
 };
 
 const int kBlockSizes[] = {-1, 1, 2, 5, 64};
-const int kBlockSizeCount = GOOGLE_ARRAYSIZE(kBlockSizes);
+const int kBlockSizeCount = ABSL_ARRAYSIZE(kBlockSizes);
 
 TEST(ObjCHelper, ParseSimple_BasicsSuccess) {
   const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
@@ -340,7 +340,7 @@
       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), "'");
+        absl::StrCat("error: dummy Line ", std::get<2>(test), ", Rejected '", std::get<1>(test), "'");
       EXPECT_EQ(err_str, expected_err);
     }
   }
@@ -362,7 +362,7 @@
       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),
+        absl::StrCat("error: dummy Line ", std::get<2>(test),
                ", ConsumeLine failed without setting an error.");
       EXPECT_EQ(err_str, expected_err);
     }
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
index 99d7581..087bd8f 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -31,9 +31,9 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/compiler/objectivec/objectivec_map_field.h"
+#include "google/protobuf/compiler/objectivec/objectivec_helpers.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
index d9aa387..c16e818 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -33,7 +33,7 @@
 
 #include <map>
 #include <string>
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include "google/protobuf/compiler/objectivec/objectivec_field.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index 4ebb75c..945d095 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -32,16 +32,24 @@
 #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>
+#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 "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.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 {
@@ -449,7 +457,7 @@
         "typedef struct $classname$__storage_ {\n"
         "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
         "classname", class_name_,
-        "sizeof_has_storage", StrCat(sizeof_has_storage));
+        "sizeof_has_storage", absl::StrCat(sizeof_has_storage));
     printer->Indent();
 
     for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -558,7 +566,7 @@
         printer->Print(
             "\n        \"$data$\"",
             "data", EscapeTrigraphs(
-                CEscape(text_format_data_str.substr(i, kBytesPerLine))));
+                absl::CEscape(text_format_data_str.substr(i, kBytesPerLine))));
       }
       printer->Print(
           ";\n"
@@ -570,8 +578,8 @@
           "    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));
+                       "start", absl::StrCat(sorted_extensions[i]->start),
+                       "end", absl::StrCat(sorted_extensions[i]->end));
       }
       printer->Print(
           "    };\n"
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
index 9d14430..641a518 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -34,10 +34,10 @@
 #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 "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"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
index 2ff0b44..e889c6e 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -31,9 +31,9 @@
 #include <map>
 #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 "google/protobuf/compiler/objectivec/objectivec_message_field.h"
+#include "google/protobuf/compiler/objectivec/objectivec_helpers.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
index 49a84fb..12e191e 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -33,7 +33,7 @@
 
 #include <map>
 #include <string>
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include "google/protobuf/compiler/objectivec/objectivec_field.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
index 1bef293..269cd52 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -31,10 +31,18 @@
 #include <map>
 #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 "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/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
 
 namespace google {
 namespace protobuf {
@@ -46,7 +54,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);
 
@@ -65,7 +73,7 @@
 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) {
@@ -84,7 +92,7 @@
         "$enum_name$_$field_name$ = $field_number$,\n",
         "enum_name", enum_name,
         "field_name", field_name,
-        "field_number", StrCat(field->number()));
+        "field_number", absl::StrCat(field->number()));
   }
   printer->Outdent();
   printer->Print(
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
index 034f07f..27e9c2a 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -34,8 +34,8 @@
 #include <string>
 #include <set>
 #include <vector>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
index 1fefde5..2c30d6b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -31,10 +31,18 @@
 #include <map>
 #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 "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/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
 
 namespace google {
 namespace protobuf {
@@ -150,7 +158,7 @@
 void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_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(has_base);
     variables_["storage_offset_comment"] =
         "  // Stored in _has_storage_ to save space.";
   }
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
index 06a1528..8948b48 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
+++ b/src/google/protobuf/compiler/objectivec/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/objectivec_field.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 5bd37d1..4cae1a1 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -34,34 +34,36 @@
 //
 // Recursive descent FTW.
 
-#include <google/protobuf/compiler/parser.h>
+#include "google/protobuf/compiler/parser.h"
 
 #include <float.h>
 
 #include <cstdint>
 #include <limits>
+#include <tuple>
 #include <unordered_map>
 #include <unordered_set>
 
-#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 "google/protobuf/stubs/strutil.h"
+#include "absl/base/casts.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.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 {
 
+using ::google::protobuf::internal::DownCast;
+
 typedef std::unordered_map<std::string, FieldDescriptorProto::Type> TypeNameMap;
 
 const TypeNameMap& GetTypeNameTable() {
@@ -634,14 +636,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 +683,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 +694,6 @@
   DO(ConsumeEndOfDeclaration(";", &syntax_location));
 
   syntax_identifier_ = syntax;
-
   if (syntax != "proto2" && syntax != "proto3" &&
       !stop_after_syntax_identifier_) {
     AddError(syntax_token.line, syntax_token.column,
@@ -1084,7 +1089,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 +1288,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,7 +1311,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;
     }
 
@@ -1346,7 +1351,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 +1479,7 @@
   }
 
   UninterpretedOption* uninterpreted_option =
-      down_cast<UninterpretedOption*>(options->GetReflection()->AddMessage(
+      DownCast<UninterpretedOption*>(options->GetReflection()->AddMessage(
           options, uninterpreted_option_field));
 
   // Parse dot-separated name.
@@ -2395,33 +2400,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..ccd3e5a 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -42,13 +42,13 @@
 #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 "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
@@ -545,8 +547,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
@@ -597,6 +597,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..3b32451 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -32,26 +32,26 @@
 //  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/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 <gtest/gtest.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/map_util.h>
+#include "absl/strings/str_join.h"
+#include "absl/strings/substitute.h"
 
 namespace google {
 namespace protobuf {
@@ -69,11 +69,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);
   }
 };
 
@@ -264,6 +264,7 @@
                   "song_name_1.") != std::string::npos);
 }
 
+
 // ===================================================================
 
 typedef ParserTest ParseMessageTest;
@@ -2401,7 +2402,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 +2678,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 +2710,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);
diff --git a/src/google/protobuf/compiler/php/BUILD.bazel b/src/google/protobuf/compiler/php/BUILD.bazel
new file mode 100644
index 0000000..5911760
--- /dev/null
+++ b/src/google/protobuf/compiler/php/BUILD.bazel
@@ -0,0 +1,44 @@
+################################################################################
+# 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 = "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 = [
+        "//:protobuf",
+        "//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/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc
index f3aa92f..7c1daec 100644
--- a/src/google/protobuf/compiler/php/php_generator.cc
+++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -28,18 +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 <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 "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/plugin.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/str_replace.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+
 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";
@@ -334,7 +338,7 @@
                                       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 = "";
 
@@ -347,7 +351,7 @@
 
   // 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;
   } else {
@@ -371,12 +375,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 +507,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 +767,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 +786,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 +916,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 +926,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 +944,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");
@@ -1235,7 +1239,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 +1259,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(
@@ -1367,7 +1371,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 +1471,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 +1479,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 +1512,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 +1598,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 +1606,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 +1642,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 +1753,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 +1952,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 +2041,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 +2193,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 +2201,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 +2243,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 +2263,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 +2326,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);
@@ -2394,11 +2390,11 @@
                             std::string* error) const {
   Options options;
 
-  for (const auto& option : Split(parameter, ",", true)) {
-    const std::vector<std::string> option_pair = Split(option, "=", true);
+  for (const auto& option : absl::StrSplit(parameter, ",", absl::SkipEmpty())) {
+    const std::vector<std::string> option_pair = absl::StrSplit(option, "=", absl::SkipEmpty());
     if (HasPrefixString(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..5007c71 100644
--- a/src/google/protobuf/compiler/php/php_generator.h
+++ b/src/google/protobuf/compiler/php/php_generator.h
@@ -31,12 +31,12 @@
 #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/descriptor.h"
 
 #include <string>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -87,6 +87,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..b7e5c0e 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -30,7 +30,7 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#include <google/protobuf/compiler/plugin.h>
+#include "google/protobuf/compiler/plugin.h"
 
 #include <iostream>
 #include <set>
@@ -41,14 +41,14 @@
 #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..bcaf8d5 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -102,6 +102,8 @@
   ~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_),
@@ -116,6 +118,8 @@
   ~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_),
@@ -130,6 +134,8 @@
   ~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_),
@@ -144,6 +150,8 @@
   ~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_),
@@ -152,10 +160,10 @@
   ~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)},
+  { 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[] = {
@@ -190,7 +198,7 @@
 static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = {
   &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
 };
-static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once;
+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,
     "google/protobuf/compiler/plugin.proto",
@@ -234,6 +242,8 @@
 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;
   }
@@ -558,6 +568,8 @@
 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;
   }
@@ -910,6 +922,8 @@
 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;
   }
@@ -1300,6 +1314,8 @@
 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;
   }
@@ -1609,4 +1625,4 @@
 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 97bf2f0..dc3712a 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,21 +19,21 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto PROTOC_EXPORT
 #ifdef major
 #undef major
@@ -92,11 +92,15 @@
   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);
+  return CodeGeneratorResponse_Feature_Name(static_cast<CodeGeneratorResponse_Feature>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, CodeGeneratorResponse_Feature* value) {
+    ::absl::string_view name, CodeGeneratorResponse_Feature* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<CodeGeneratorResponse_Feature>(
     CodeGeneratorResponse_Feature_descriptor(), name, value);
 }
@@ -212,7 +216,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:
@@ -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:
@@ -653,7 +657,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:
@@ -878,7 +882,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:
@@ -920,7 +924,7 @@
       "Incorrect type passed to function Feature_Name.");
     return CodeGeneratorResponse_Feature_Name(enum_t_value);
   }
-  static inline bool Feature_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool Feature_Parse(::absl::string_view name,
       Feature* value) {
     return CodeGeneratorResponse_Feature_Parse(name, value);
   }
@@ -1140,9 +1144,7 @@
   _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,8 +1202,7 @@
   // @@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) {
@@ -1221,8 +1222,7 @@
   // @@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) {
@@ -1287,9 +1287,7 @@
   _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;
 }
@@ -1486,9 +1484,7 @@
   _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;
 }
@@ -1554,9 +1550,7 @@
   _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;
 }
@@ -1622,9 +1616,7 @@
   _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;
 }
@@ -1781,9 +1773,7 @@
   _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;
 }
@@ -1897,5 +1887,5 @@
 
 // @@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_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..0f46a45 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.
diff --git a/src/google/protobuf/compiler/python/BUILD.bazel b/src/google/protobuf/compiler/python/BUILD.bazel
new file mode 100644
index 0000000..b45a00b
--- /dev/null
+++ b/src/google/protobuf/compiler/python/BUILD.bazel
@@ -0,0 +1,68 @@
+################################################################################
+# 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__",
+    ],
+    deps = [
+        "//:protobuf",
+        "//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..3d580ad 100644
--- a/src/google/protobuf/compiler/python/generator.cc
+++ b/src/google/protobuf/compiler/python/generator.cc
@@ -42,7 +42,7 @@
 // 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>
@@ -52,17 +52,20 @@
 #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 "google/protobuf/stubs/strutil.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/stubs/stringprintf.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/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
@@ -90,29 +93,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 +112,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()) {
@@ -173,9 +154,9 @@
     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 +193,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 +240,105 @@
   // 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 = StripPrefixString(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 +350,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 +385,9 @@
 
     std::string module_name = ModuleName(filename);
     std::string module_alias = ModuleAlias(filename);
+    if (!opensource_runtime_) {
+      module_name = StripPrefixString(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 +418,9 @@
   // 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 = StripPrefixString(module_name, kThirdPartyPrefix);
+    }
     printer_->Print("from $module$ import *\n", "module", module_name);
   }
   printer_->Print("\n");
@@ -373,7 +434,7 @@
   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 +450,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,
@@ -467,11 +524,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 +537,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");
 }
 
@@ -535,13 +588,12 @@
 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 = StripPrefixString(module_name, kThirdPartyPrefix);
+  }
   printer_->Print("__module__ = '$module_name$'\n", "module_name", module_name);
 }
 
@@ -634,8 +686,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 +697,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"] = "";
@@ -728,14 +780,12 @@
   PrintNestedMessages(message_descriptor, qualified_name, to_register);
   std::map<std::string, 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 = StripPrefixString(module_name, kThirdPartyPrefix);
+  }
   printer_->Print("'__module__' : '$module_name$'\n", "module_name",
                   module_name);
   printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n",
@@ -894,7 +944,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());
 }
@@ -991,8 +1041,8 @@
   descriptor.options().SerializeToString(&options_string);
   std::map<std::string, 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 +1058,7 @@
   if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
     return "None";
   } else {
-    return "b'" + CEscape(serialized_options) + "'";
+    return "b'" + absl::CEscape(serialized_options) + "'";
   }
 }
 
@@ -1020,11 +1070,11 @@
   std::map<std::string, 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 +1156,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 +1186,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 +1194,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 +1225,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 +1316,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_);
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..711d555 100644
--- a/src/google/protobuf/compiler/python/helpers.cc
+++ b/src/google/protobuf/compiler/python/helpers.cc
@@ -28,14 +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/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 "google/protobuf/stubs/strutil.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
 
 namespace google {
 namespace protobuf {
@@ -68,7 +70,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;
@@ -101,6 +103,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..1fff3c9 100644
--- a/src/google/protobuf/compiler/python/helpers.h
+++ b/src/google/protobuf/compiler/python/helpers.h
@@ -33,7 +33,9 @@
 
 #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 {
@@ -49,6 +51,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..b8f25cf 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/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "absl/strings/str_split.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..7c723ef 100644
--- a/src/google/protobuf/compiler/python/pyi_generator.cc
+++ b/src/google/protobuf/compiler/python/pyi_generator.cc
@@ -28,61 +28,57 @@
 // (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/strings/ascii.h"
+#include "google/protobuf/stubs/strutil.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,7 +152,6 @@
 
 void PyiGenerator::PrintImportForDescriptor(
     const FileDescriptor& desc,
-    std::map<std::string, std::string>* import_map,
     std::set<std::string>* seen_aliases) const {
   const std::string& filename = desc.name();
   std::string module_name = StrippedModuleName(filename);
@@ -176,21 +171,19 @@
   }
   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;
   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 +195,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 +207,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 +264,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 +282,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 +300,22 @@
       "class $enum_name$(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):\n"
       "    __slots__ = []\n",
       "enum_name", enum_name);
+  Annotate("enum_name", &enum_descriptor);
 }
 
-// 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) 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;
+    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 +323,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 +352,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 +363,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 +378,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 +393,15 @@
   }
   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 +414,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 +452,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 +491,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 +500,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 +510,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()) {
@@ -553,78 +540,87 @@
   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 (HasSuffixString(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 printer(output.get(), '$',
+                      annotate_code ? &annotation_collector : nullptr);
   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..7f1e5d8 100644
--- a/src/google/protobuf/compiler/python/pyi_generator.h
+++ b/src/google/protobuf/compiler/python/pyi_generator.h
@@ -39,11 +39,11 @@
 #include <set>
 #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 {
@@ -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.
@@ -76,38 +78,35 @@
 
  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;
+  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) 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 std::map<std::string, std::string> import_map_;
 };
 
 }  // namespace python
@@ -115,6 +114,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..bb31797 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -1,6 +1,6 @@
 #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..73b0fcf
--- /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 = [
+        "//:protobuf",
+        "//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..2408dcd 100644
--- a/src/google/protobuf/compiler/scc.h
+++ b/src/google/protobuf/compiler/scc.h
@@ -33,12 +33,12 @@
 
 #include <map>
 
-#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 "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,6 +64,8 @@
 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;
@@ -151,15 +153,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 764f9ab..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,25 +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/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) {
@@ -113,7 +105,7 @@
   }
 
   // Setup STARTUPINFO to redirect handles.
-  STARTUPINFOA startup_info;
+  STARTUPINFOW startup_info;
   ZeroMemory(&startup_info, sizeof(startup_info));
   startup_info.cb = sizeof(startup_info);
   startup_info.dwFlags = STARTF_USESTDHANDLES;
@@ -125,17 +117,30 @@
     GOOGLE_LOG(FATAL) << "GetStdHandle: " << Win32ErrorMessage(GetLastError());
   }
 
+  // get wide string version of program as the path may contain non-ascii characters
+  std::wstring wprogram;
+  if (!io::win32::strings::utf8_to_wcs(program.c_str(), &wprogram)) {
+    GOOGLE_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError());
+  }
+
   // Invoking cmd.exe allows for '.bat' files from the path as well as '.exe'.
+  std::string command_line = "cmd.exe /c \"" + program + "\"";
+
+  // get wide string version of command line as the path may contain non-ascii characters
+  std::wstring wcommand_line;
+  if (!io::win32::strings::utf8_to_wcs(command_line.c_str(), &wcommand_line)) {
+    GOOGLE_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError());
+  }
+
   // Using a malloc'ed string because CreateProcess() can mutate its second
   // parameter.
-  char* command_line =
-      portable_strdup(("cmd.exe /c \"" + program + "\"").c_str());
+  wchar_t *wcommand_line_copy = _wcsdup(wcommand_line.c_str());
 
   // Create the process.
   PROCESS_INFORMATION process_info;
 
-  if (CreateProcessA((search_mode == SEARCH_PATH) ? nullptr : program.c_str(),
-                     (search_mode == SEARCH_PATH) ? command_line : nullptr,
+  if (CreateProcessW((search_mode == SEARCH_PATH) ? nullptr : wprogram.c_str(),
+                     (search_mode == SEARCH_PATH) ? wcommand_line_copy : NULL,
                      nullptr,  // process security attributes
                      nullptr,  // thread security attributes
                      TRUE,     // inherit handles?
@@ -155,7 +160,7 @@
 
   CloseHandleOrDie(stdin_pipe_read);
   CloseHandleOrDie(stdout_pipe_write);
-  free(command_line);
+  free(wcommand_line_copy);
 }
 
 bool Subprocess::Communicate(const Message& input, Message* output,
@@ -259,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;
   }
 
@@ -303,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.
@@ -457,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?";
@@ -470,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..ddebcf6 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -32,7 +32,7 @@
 //  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>
@@ -44,53 +44,47 @@
 #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 "google/protobuf/stubs/strutil.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 "google/protobuf/stubs/stringprintf.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,27 +1610,23 @@
     }
   }
 
-  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
@@ -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,13 +2469,13 @@
   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());
     case CPPTYPE_DOUBLE:
@@ -2538,10 +2484,10 @@
       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();
         }
@@ -2562,7 +2508,9 @@
   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 (syntax() == SYNTAX_PROTO3
+  ) proto->set_syntax(SyntaxName(syntax()));
+
 
   for (int i = 0; i < dependency_count(); i++) {
     proto->add_dependency(dependency(i)->name());
@@ -2680,9 +2628,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 +2837,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 +2849,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();
@@ -2953,10 +2901,10 @@
   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");
+    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 +2933,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 +2941,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 +2965,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 +2980,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 +2988,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 +3005,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 +3044,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 +3053,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 +3066,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 +3085,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 +3094,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 +3121,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 +3143,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 +3174,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 +3182,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 +3194,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 +3212,7 @@
       contents->append(", ");
     }
     contents->append("json_name = \"");
-    contents->append(CEscape(json_name()));
+    contents->append(absl::CEscape(json_name()));
     contents->append("\"");
   }
 
@@ -3316,7 +3262,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 +3274,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 +3301,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 +3310,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 +3326,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 +3360,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 +3391,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 +3426,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 +3434,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 +3644,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 +3667,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 +3895,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 +4013,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,
@@ -4275,7 +4221,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 +4251,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 +4270,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 +4283,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 +4383,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 +4403,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 +4456,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 +4525,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 +4536,7 @@
 }
 
 FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
-    StringPiece name, internal::FlatAllocator& alloc) const {
+    absl::string_view name, internal::FlatAllocator& alloc) const {
   if (mutex_) {
     mutex_->AssertHeld();
   }
@@ -4982,7 +4926,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 +5096,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 +5128,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 +5165,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 +5303,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 +5397,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 +5405,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 +5426,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 +5438,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 +5446,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 +5460,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 +5471,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 +5519,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).
@@ -5673,8 +5616,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 +5699,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 +5741,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 +5990,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 +5998,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 +6017,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 +6025,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 +6223,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 +6343,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 +6393,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 +6534,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 +6555,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 +6653,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 +6897,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 +7255,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,
@@ -8154,22 +8100,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 +8175,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 +8188,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 +8228,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 +8249,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 +8258,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 +8266,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 +8276,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 1b8728e..dfe8d42 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 {
@@ -896,7 +903,7 @@
 
   // formats the default value appropriately and returns it as a string.
   // Must have a default value to call this. If quote_string_type is true, then
-  // types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped.
+  // types of CPPTYPE_STRING will be surrounded by quotes and CEscaped.
   std::string DefaultValueAsString(bool quote_string_type) const;
 
   // Helper function that returns the field type name for DebugString.
@@ -941,7 +948,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 +993,6 @@
   friend class FileDescriptor;
   friend class Descriptor;
   friend class OneofDescriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FieldDescriptor, 72);
@@ -996,6 +1002,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 +1078,6 @@
   OneofDescriptor() {}
   friend class DescriptorBuilder;
   friend class Descriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(OneofDescriptor, 40);
@@ -1079,6 +1089,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 +1114,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;
@@ -1157,7 +1172,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 +1253,6 @@
   friend class FileDescriptor;
   friend class DescriptorPool;
   friend class Reflection;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(EnumDescriptor, 72);
@@ -1253,6 +1267,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 +1342,6 @@
   friend class DescriptorPool;
   friend class FileDescriptorTables;
   friend class Reflection;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(EnumValueDescriptor, 32);
@@ -1334,6 +1352,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 +1380,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 +1429,6 @@
   friend class DescriptorBuilder;
   friend class FileDescriptor;
   friend class MethodDescriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(ServiceDescriptor, 48);
@@ -1419,6 +1441,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 +1522,6 @@
   MethodDescriptor() {}
   friend class DescriptorBuilder;
   friend class ServiceDescriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(MethodDescriptor, 64);
@@ -1507,6 +1533,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 +1605,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 +1619,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:
@@ -1660,7 +1695,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 +1734,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 +1796,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 +1810,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 +1844,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 +1862,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 +1906,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 +2018,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 +2040,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 +2068,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 +2082,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 +2110,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);
 };
 
 
@@ -2219,9 +2256,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 +2275,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 +2322,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_);
 }
@@ -2431,10 +2468,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..b8a24a9 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -48,6 +48,7 @@
   , /*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 {
@@ -482,7 +483,8 @@
   , /*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{}) {}
@@ -507,7 +509,7 @@
 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 const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[7];
 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) = {
@@ -517,6 +519,8 @@
   ~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_),
@@ -524,6 +528,8 @@
   ~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_),
@@ -536,6 +542,7 @@
   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,
@@ -545,15 +552,18 @@
   ~0u,
   ~0u,
   ~0u,
-  3,
   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_),
@@ -566,6 +576,8 @@
   ~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,
@@ -576,6 +588,8 @@
   ~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_),
@@ -602,6 +616,8 @@
   ~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_),
@@ -609,6 +625,8 @@
   ~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_),
@@ -637,6 +655,8 @@
   ~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,
@@ -647,6 +667,8 @@
   ~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,
@@ -657,6 +679,8 @@
   ~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_),
@@ -673,6 +697,8 @@
   ~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_),
@@ -685,6 +711,8 @@
   ~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_),
@@ -697,6 +725,8 @@
   ~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_),
@@ -715,6 +745,8 @@
   ~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_),
@@ -763,6 +795,8 @@
   ~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_),
@@ -779,6 +813,8 @@
   ~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_),
@@ -801,6 +837,8 @@
   ~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_),
@@ -808,6 +846,8 @@
   ~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_),
@@ -820,6 +860,8 @@
   ~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,
@@ -830,6 +872,8 @@
   ~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,
@@ -840,6 +884,8 @@
   ~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_),
@@ -852,6 +898,8 @@
   ~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,
@@ -862,6 +910,8 @@
   ~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_),
@@ -882,6 +932,8 @@
   ~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_),
@@ -898,6 +950,8 @@
   ~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_),
@@ -905,50 +959,56 @@
   ~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)},
+  { 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[] = {
@@ -985,7 +1045,7 @@
   "\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"
+  "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"
@@ -997,147 +1057,151 @@
   "\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"
+  "(\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\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"
+  "*\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once;
+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,
@@ -1319,6 +1383,29 @@
 constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MAX;
 constexpr int MethodOptions::IdempotencyLevel_ARRAYSIZE;
 #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))
 
 // ===================================================================
 
@@ -1512,6 +1599,8 @@
 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 +1609,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 +1653,7 @@
     , decltype(_impl_.name_){}
     , decltype(_impl_.package_){}
     , decltype(_impl_.syntax_){}
+    , decltype(_impl_.edition_){}
     , decltype(_impl_.options_){nullptr}
     , decltype(_impl_.source_code_info_){nullptr}};
 
@@ -1589,6 +1682,14 @@
     _this->_impl_.syntax_.Set(from._internal_syntax(), 
       _this->GetArenaForAllocation());
   }
+  _impl_.edition_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+    _impl_.edition_.Set("", GetArenaForAllocation());
+  #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  if (from._internal_has_edition()) {
+    _this->_impl_.edition_.Set(from._internal_edition(), 
+      _this->GetArenaForAllocation());
+  }
   if (from._internal_has_options()) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::FileOptions(*from._impl_.options_);
   }
@@ -1615,6 +1716,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 +1732,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 +1759,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_;
 }
@@ -1675,7 +1782,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 +1793,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();
     }
@@ -1858,6 +1968,18 @@
         } 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;
     }  // switch
@@ -1952,14 +2074,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 +2109,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);
@@ -2058,7 +2190,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 +2212,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_);
@@ -2121,7 +2260,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 +2271,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());
     }
@@ -2190,6 +2332,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_)
@@ -2209,6 +2355,8 @@
 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;
   }
@@ -2493,6 +2641,8 @@
 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;
   }
@@ -2730,6 +2880,8 @@
 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;
   }
@@ -3505,6 +3657,8 @@
 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;
   }
@@ -3768,9 +3922,9 @@
       // 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);
+          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());
@@ -3781,9 +3935,9 @@
       // 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);
+          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());
@@ -4186,6 +4340,8 @@
 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;
   }
@@ -4461,6 +4617,8 @@
 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;
   }
@@ -4698,6 +4856,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;
   }
@@ -5084,6 +5244,8 @@
 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;
   }
@@ -5395,6 +5557,8 @@
 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;
   }
@@ -5706,6 +5870,8 @@
 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;
   }
@@ -6163,6 +6329,8 @@
 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;
   }
@@ -6542,9 +6710,9 @@
       // 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);
+          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());
@@ -7282,6 +7450,8 @@
 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;
   }
@@ -7630,6 +7800,8 @@
 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;
   }
@@ -7749,9 +7921,9 @@
       // 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);
+          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());
@@ -7789,9 +7961,9 @@
       // 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);
+          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());
@@ -8286,6 +8458,8 @@
 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;
   }
@@ -8578,6 +8752,8 @@
 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;
   }
@@ -8827,6 +9003,8 @@
 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;
   }
@@ -9076,6 +9254,8 @@
 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;
   }
@@ -9179,9 +9359,9 @@
       // 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);
+          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());
@@ -9377,6 +9557,8 @@
 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;
   }
@@ -9653,6 +9835,8 @@
 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;
   }
@@ -10122,6 +10306,8 @@
 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;
   }
@@ -10341,7 +10527,7 @@
 
   // 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 +10536,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);
@@ -10413,8 +10599,7 @@
         ::_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;
   }
 
@@ -10427,8 +10612,7 @@
         ::_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;
   }
 
@@ -10716,6 +10900,8 @@
 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 +10911,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,7 +10932,8 @@
     , /*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();
@@ -10755,8 +10945,8 @@
       _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 +10962,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
@@ -10809,10 +11000,10 @@
   if (cached_has_bits & 0x00000001u) {
     _impl_.source_file_.ClearNonDefaultToEmpty();
   }
-  if (cached_has_bits & 0x00000006u) {
+  if (cached_has_bits & 0x0000000eu) {
     ::memset(&_impl_.begin_, 0, static_cast<size_t>(
-        reinterpret_cast<char*>(&_impl_.end_) -
-        reinterpret_cast<char*>(&_impl_.begin_)) + sizeof(_impl_.end_));
+        reinterpret_cast<char*>(&_impl_.semantic_) -
+        reinterpret_cast<char*>(&_impl_.begin_)) + sizeof(_impl_.semantic_));
   }
   _impl_._has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
@@ -10866,6 +11057,19 @@
         } 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;
     }  // switch
@@ -10898,7 +11102,7 @@
 
   // 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 +11132,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);
@@ -10953,13 +11164,12 @@
         ::_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 +11187,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_);
 }
@@ -10998,7 +11214,7 @@
 
   _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 +11224,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,8 +11255,8 @@
       &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_));
@@ -11348,4 +11567,4 @@
 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 2d9c790..902b8e7 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,20 +19,20 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -190,11 +190,15 @@
   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);
+  return FieldDescriptorProto_Type_Name(static_cast<FieldDescriptorProto_Type>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Type* value) {
+    ::absl::string_view name, FieldDescriptorProto_Type* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldDescriptorProto_Type>(
     FieldDescriptorProto_Type_descriptor(), name, value);
 }
@@ -214,11 +218,15 @@
   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);
+  return FieldDescriptorProto_Label_Name(static_cast<FieldDescriptorProto_Label>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Label* value) {
+    ::absl::string_view name, FieldDescriptorProto_Label* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldDescriptorProto_Label>(
     FieldDescriptorProto_Label_descriptor(), name, value);
 }
@@ -238,11 +246,15 @@
   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);
+  return FileOptions_OptimizeMode_Name(static_cast<FileOptions_OptimizeMode>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FileOptions_OptimizeMode* value) {
+    ::absl::string_view name, FileOptions_OptimizeMode* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FileOptions_OptimizeMode>(
     FileOptions_OptimizeMode_descriptor(), name, value);
 }
@@ -262,11 +274,15 @@
   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);
+  return FieldOptions_CType_Name(static_cast<FieldOptions_CType>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_CType* value) {
+    ::absl::string_view name, FieldOptions_CType* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldOptions_CType>(
     FieldOptions_CType_descriptor(), name, value);
 }
@@ -286,11 +302,15 @@
   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);
+  return FieldOptions_JSType_Name(static_cast<FieldOptions_JSType>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_JSType* value) {
+    ::absl::string_view name, FieldOptions_JSType* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldOptions_JSType>(
     FieldOptions_JSType_descriptor(), name, value);
 }
@@ -310,14 +330,46 @@
   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);
+  return MethodOptions_IdempotencyLevel_Name(static_cast<MethodOptions_IdempotencyLevel>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, MethodOptions_IdempotencyLevel* value) {
+    ::absl::string_view name, MethodOptions_IdempotencyLevel* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<MethodOptions_IdempotencyLevel>(
     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 = GeneratedCodeInfo_Annotation_Semantic_NONE;
+constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation_Semantic_Semantic_MAX = GeneratedCodeInfo_Annotation_Semantic_ALIAS;
+constexpr int GeneratedCodeInfo_Annotation_Semantic_Semantic_ARRAYSIZE = GeneratedCodeInfo_Annotation_Semantic_Semantic_MAX + 1;
+
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* GeneratedCodeInfo_Annotation_Semantic_descriptor();
+template<typename T>
+inline const std::string& GeneratedCodeInfo_Annotation_Semantic_Name(T enum_t_value) {
+  static_assert(::std::is_same<T, GeneratedCodeInfo_Annotation_Semantic>::value ||
+    ::std::is_integral<T>::value,
+    "Incorrect type passed to function GeneratedCodeInfo_Annotation_Semantic_Name.");
+  return GeneratedCodeInfo_Annotation_Semantic_Name(static_cast<GeneratedCodeInfo_Annotation_Semantic>(enum_t_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 :
@@ -430,7 +482,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:
@@ -594,7 +646,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 +674,7 @@
     kNameFieldNumber = 1,
     kPackageFieldNumber = 2,
     kSyntaxFieldNumber = 12,
+    kEditionFieldNumber = 13,
     kOptionsFieldNumber = 8,
     kSourceCodeInfoFieldNumber = 9,
   };
@@ -819,6 +872,24 @@
   std::string* _internal_mutable_syntax();
   public:
 
+  // optional string edition = 13;
+  bool has_edition() const;
+  private:
+  bool _internal_has_edition() const;
+  public:
+  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:
@@ -875,6 +946,7 @@
     ::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_;
   };
@@ -993,7 +1065,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:
@@ -1188,7 +1260,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:
@@ -1363,7 +1435,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:
@@ -1717,7 +1789,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:
@@ -2073,7 +2145,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:
@@ -2145,7 +2217,7 @@
       "Incorrect type passed to function Type_Name.");
     return FieldDescriptorProto_Type_Name(enum_t_value);
   }
-  static inline bool Type_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool Type_Parse(::absl::string_view name,
       Type* value) {
     return FieldDescriptorProto_Type_Parse(name, value);
   }
@@ -2177,7 +2249,7 @@
       "Incorrect type passed to function Label_Name.");
     return FieldDescriptorProto_Label_Name(enum_t_value);
   }
-  static inline bool Label_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool Label_Parse(::absl::string_view name,
       Label* value) {
     return FieldDescriptorProto_Label_Parse(name, value);
   }
@@ -2507,7 +2579,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:
@@ -2692,7 +2764,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:
@@ -2867,7 +2939,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:
@@ -3120,7 +3192,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:
@@ -3320,7 +3392,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:
@@ -3525,7 +3597,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:
@@ -3780,7 +3852,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:
@@ -3822,7 +3894,7 @@
       "Incorrect type passed to function OptimizeMode_Name.");
     return FileOptions_OptimizeMode_Name(enum_t_value);
   }
-  static inline bool OptimizeMode_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool OptimizeMode_Parse(::absl::string_view name,
       OptimizeMode* value) {
     return FileOptions_OptimizeMode_Parse(name, value);
   }
@@ -4519,7 +4591,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:
@@ -4936,7 +5008,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:
@@ -4978,7 +5050,7 @@
       "Incorrect type passed to function CType_Name.");
     return FieldOptions_CType_Name(enum_t_value);
   }
-  static inline bool CType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool CType_Parse(::absl::string_view name,
       CType* value) {
     return FieldOptions_CType_Parse(name, value);
   }
@@ -5010,7 +5082,7 @@
       "Incorrect type passed to function JSType_Name.");
     return FieldOptions_JSType_Name(enum_t_value);
   }
-  static inline bool JSType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool JSType_Parse(::absl::string_view name,
       JSType* value) {
     return FieldOptions_JSType_Parse(name, value);
   }
@@ -5462,7 +5534,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:
@@ -5818,7 +5890,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:
@@ -6205,7 +6277,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:
@@ -6577,7 +6649,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:
@@ -6949,7 +7021,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:
@@ -6991,7 +7063,7 @@
       "Incorrect type passed to function IdempotencyLevel_Name.");
     return MethodOptions_IdempotencyLevel_Name(enum_t_value);
   }
-  static inline bool IdempotencyLevel_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool IdempotencyLevel_Parse(::absl::string_view name,
       IdempotencyLevel* value) {
     return MethodOptions_IdempotencyLevel_Parse(name, value);
   }
@@ -7368,7 +7440,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:
@@ -7551,7 +7623,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:
@@ -7823,7 +7895,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:
@@ -7962,9 +8034,9 @@
     ::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_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _path_cached_byte_size_;
     ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > span_;
-    mutable std::atomic<int> _span_cached_byte_size_;
+    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_;
@@ -8084,7 +8156,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:
@@ -8250,7 +8322,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 +8337,38 @@
 
   // nested types ----------------------------------------------------
 
+  typedef GeneratedCodeInfo_Annotation_Semantic 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 enum_t_value) {
+    static_assert(::std::is_same<T, Semantic>::value ||
+      ::std::is_integral<T>::value,
+      "Incorrect type passed to function Semantic_Name.");
+    return GeneratedCodeInfo_Annotation_Semantic_Name(enum_t_value);
+  }
+  static inline bool Semantic_Parse(::absl::string_view name,
+      Semantic* value) {
+    return GeneratedCodeInfo_Annotation_Semantic_Parse(name, value);
+  }
+
   // accessors -------------------------------------------------------
 
   enum : int {
@@ -8272,6 +8376,7 @@
     kSourceFileFieldNumber = 2,
     kBeginFieldNumber = 3,
     kEndFieldNumber = 4,
+    kSemanticFieldNumber = 5,
   };
   // repeated int32 path = 1 [packed = true];
   int path_size() const;
@@ -8339,6 +8444,19 @@
   void _internal_set_end(int32_t value);
   public:
 
+  // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
+  bool has_semantic() const;
+  private:
+  bool _internal_has_semantic() const;
+  public:
+  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)
  private:
   class _Internal;
@@ -8350,10 +8468,11 @@
     ::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_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _path_cached_byte_size_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr source_file_;
     int32_t begin_;
     int32_t end_;
+    int semantic_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
@@ -8470,7 +8589,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:
@@ -8626,9 +8745,7 @@
   _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;
 }
@@ -8694,9 +8811,7 @@
   _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,8 +8865,7 @@
   // @@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) {
@@ -8771,8 +8885,7 @@
   // @@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) {
@@ -9046,7 +9159,7 @@
 
 // optional .google.protobuf.FileOptions options = 8;
 inline bool FileDescriptorProto::_internal_has_options() const {
-  bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
+  bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
@@ -9055,7 +9168,7 @@
 }
 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 +9186,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 +9209,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,9 +9239,9 @@
       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)
@@ -9136,7 +9249,7 @@
 
 // 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;
+  bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.source_code_info_ != nullptr);
   return value;
 }
@@ -9145,7 +9258,7 @@
 }
 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 +9276,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 +9299,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,9 +9329,9 @@
       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)
@@ -9271,9 +9384,7 @@
   _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,6 +9403,72 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
 }
 
+// optional string edition = 13;
+inline bool FileDescriptorProto::_internal_has_edition() const {
+  bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
+  return value;
+}
+inline bool FileDescriptorProto::has_edition() const {
+  return _internal_has_edition();
+}
+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 (!_internal_has_edition()) {
+    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
@@ -9553,9 +9730,7 @@
   _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;
 }
@@ -9979,8 +10154,7 @@
   // @@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) {
@@ -10000,8 +10174,7 @@
   // @@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) {
@@ -10114,9 +10287,7 @@
   _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;
 }
@@ -10268,9 +10439,7 @@
   _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;
 }
@@ -10336,9 +10505,7 @@
   _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;
 }
@@ -10404,9 +10571,7 @@
   _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;
 }
@@ -10500,9 +10665,7 @@
   _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;
 }
@@ -10690,9 +10853,7 @@
   _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;
 }
@@ -10912,9 +11073,7 @@
   _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;
 }
@@ -11138,8 +11297,7 @@
   // @@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) {
@@ -11159,8 +11317,7 @@
   // @@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) {
@@ -11229,9 +11386,7 @@
   _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;
 }
@@ -11419,9 +11574,7 @@
   _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;
 }
@@ -11621,9 +11774,7 @@
   _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;
 }
@@ -11689,9 +11840,7 @@
   _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;
 }
@@ -11757,9 +11906,7 @@
   _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;
 }
@@ -11975,9 +12122,7 @@
   _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;
 }
@@ -12043,9 +12188,7 @@
   _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;
 }
@@ -12224,9 +12367,7 @@
   _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;
 }
@@ -12460,9 +12601,7 @@
   _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;
 }
@@ -12528,9 +12667,7 @@
   _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;
 }
@@ -12596,9 +12733,7 @@
   _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;
 }
@@ -12664,9 +12799,7 @@
   _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;
 }
@@ -12732,9 +12865,7 @@
   _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;
 }
@@ -12800,9 +12931,7 @@
   _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;
 }
@@ -12868,9 +12997,7 @@
   _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;
 }
@@ -13767,9 +13894,7 @@
   _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;
 }
@@ -13907,9 +14032,7 @@
   _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;
 }
@@ -14059,9 +14182,7 @@
   _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;
 }
@@ -14127,9 +14248,7 @@
   _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;
 }
@@ -14293,9 +14412,7 @@
   _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;
 }
@@ -14361,9 +14478,7 @@
   _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,8 +14532,7 @@
   // @@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) {
@@ -14438,8 +14552,7 @@
   // @@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) {
@@ -14599,9 +14712,7 @@
   _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;
 }
@@ -14676,6 +14787,35 @@
   // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end)
 }
 
+// optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
+inline bool GeneratedCodeInfo_Annotation::_internal_has_semantic() const {
+  bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
+  return value;
+}
+inline bool GeneratedCodeInfo_Annotation::has_semantic() const {
+  return _internal_has_semantic();
+}
+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
@@ -14812,10 +14952,15 @@
 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_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index f8eb216..f264b13 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -86,8 +86,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.
@@ -497,6 +502,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,10 +523,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.
   optional bool map_entry = 7;
 
   reserved 8;  // javalite_serializable
@@ -604,11 +609,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
@@ -914,8 +916,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..440bf9a 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -32,14 +32,17 @@
 //  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 "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_replace.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/stubs/stl_util.h"
 
 
 namespace google {
@@ -52,7 +55,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 +120,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 +154,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,7 +188,7 @@
 // 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) &&
           super_symbol[sub_symbol.size()] == '.');
@@ -271,10 +274,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 +296,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 +314,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 +359,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 +408,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 +438,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 +456,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 +466,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 +480,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 +500,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 +536,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 +549,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 +645,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 +674,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 +702,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 +742,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 +754,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 +781,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 +800,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 +832,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 +865,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..a290045 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/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 <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 "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);
   }
 };
@@ -4244,7 +4244,7 @@
 }
 
 TEST_F(ValidationErrorTest, DebugStringReservedRangeMax) {
-  const FileDescriptor* file = BuildFile(strings::Substitute(
+  const FileDescriptor* file = BuildFile(absl::Substitute(
       "name: \"foo.proto\" "
       "enum_type { "
       "  name: \"Bar\""
@@ -5844,7 +5844,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\" } "
@@ -6129,7 +6129,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) {
@@ -7338,19 +7340,19 @@
   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 +7402,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 +7411,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 +7418,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 +7430,6 @@
  private:
   const std::string filename_;
   const std::string contents_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
 };
 
 const char* const kSourceLocationTestInput =
@@ -7523,7 +7524,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 +8428,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..747cb5b 100644
--- a/src/google/protobuf/drop_unknown_fields_test.cc
+++ b/src/google/protobuf/drop_unknown_fields_test.cc
@@ -30,9 +30,9 @@
 
 #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/unittest_drop_unknown_fields.pb.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message_lite.h"
 #include <gtest/gtest.h>
 
 using unittest_drop_unknown_fields::Foo;
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index 72766bd..b0db698 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -47,6 +47,8 @@
   ~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_),
 };
@@ -66,7 +68,7 @@
   "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;
+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,
     "google/protobuf/duration.proto",
@@ -304,4 +306,4 @@
 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 c4a94c5..4fe1e62 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,19 +19,19 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fduration_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -159,7 +159,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:
@@ -236,7 +236,7 @@
   return _internal_seconds();
 }
 inline void Duration::_internal_set_seconds(int64_t value) {
-  
+
   _impl_.seconds_ = value;
 }
 inline void Duration::set_seconds(int64_t value) {
@@ -256,7 +256,7 @@
   return _internal_nanos();
 }
 inline void Duration::_internal_set_nanos(int32_t value) {
-  
+
   _impl_.nanos_ = value;
 }
 inline void Duration::set_nanos(int32_t value) {
@@ -274,5 +274,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto_2epb_2eh
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 1c96ca2..16bce6e 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -62,7 +62,7 @@
 // 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>
@@ -70,23 +70,23 @@
 #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 +105,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 +208,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 +271,6 @@
 
   const DynamicMessageFactory::TypeInfo* type_info_;
   mutable std::atomic<int> cached_byte_size_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
 };
 
 struct DynamicMessageFactory::TypeInfo {
@@ -313,7 +298,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 +652,7 @@
 }
 
 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
-  MutexLock lock(&prototypes_mutex_);
+  absl::MutexLock lock(&prototypes_mutex_);
   return GetPrototypeNoLock(type);
 }
 
@@ -705,7 +704,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 +807,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 +825,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..bec0a1e 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -44,18 +44,18 @@
 #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/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;
 
@@ -133,12 +138,10 @@
 
   struct TypeInfo;
   std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_;
-  mutable internal::WrappedMutex prototypes_mutex_;
+  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..6dd1184 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/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 <gtest/gtest.h>
-#include <google/protobuf/test_util.h>
+#include "google/protobuf/test_util.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 3a30776..c3de546 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -44,6 +44,8 @@
   ~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)},
@@ -60,7 +62,7 @@
   "/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;
+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,
     "google/protobuf/empty.proto",
@@ -127,4 +129,4 @@
 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 00a4481..bc6bbc6 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,20 +19,20 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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>
+#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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fempty_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -145,7 +145,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:
@@ -194,5 +194,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto_2epb_2eh
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..791c1e3 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/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.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/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..2ce566a 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/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"
 
 // 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;
@@ -574,8 +579,6 @@
 
    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..0ccce3c 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/io/coded_stream.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/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..8b436bc 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -32,29 +32,31 @@
 //  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/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/text_format.h"
+#include "google/protobuf/wire_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 "google/protobuf/test_util.h"
+#include "google/protobuf/test_util2.h"
+#include "google/protobuf/stubs/stl_util.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 {
@@ -62,6 +64,7 @@
 namespace internal {
 namespace {
 
+using ::google::protobuf::internal::DownCast;
 using TestUtil::EqualsToSerialized;
 
 // This test closely mirrors third_party/protobuf/compiler/cpp/unittest.cc
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..66af752 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -46,6 +46,8 @@
   ~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) = {
@@ -64,7 +66,7 @@
   "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;
+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,
     "google/protobuf/field_mask.proto",
@@ -281,4 +283,4 @@
 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 ecc6ede..3d9c467 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,19 +19,19 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ffield_5fmask_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -159,7 +159,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:
@@ -263,8 +263,7 @@
   // @@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) {
@@ -284,8 +283,7 @@
   // @@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) {
@@ -313,5 +311,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh
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..e831079 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/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"
 
 // 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..b1b472c 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -32,29 +32,36 @@
 //  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/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 +80,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 +101,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 +114,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 +293,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 +454,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 +1055,6 @@
     return;
   }
 
-  GOOGLE_DCHECK_EQ(message1->GetOwningArena(), message2->GetOwningArena());
-
   UnsafeArenaSwap(message1, message2);
 }
 
@@ -1014,9 +1084,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 +1140,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 +1173,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 +1186,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);
@@ -2434,13 +2515,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 +2551,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 +2972,363 @@
   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::FastEr0S1", internal::TcParser::FastEr0S1},
+          {"::_pbi::TcParser::FastEr0S2", internal::TcParser::FastEr0S2},
+          {"::_pbi::TcParser::FastEr0R1", internal::TcParser::FastEr0R1},
+          {"::_pbi::TcParser::FastEr0R2", internal::TcParser::FastEr0R2},
+          {"::_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::FastEvS1", internal::TcParser::FastEvS1},
+          {"::_pbi::TcParser::FastEvS2", internal::TcParser::FastEvS2},
+          {"::_pbi::TcParser::FastEvR1", internal::TcParser::FastEvR1},
+          {"::_pbi::TcParser::FastEvR2", internal::TcParser::FastEvR2},
+          {"::_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::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, 1, 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 (fast_field.func_name.find("TcParser::FastEv") !=
+               fast_field.func_name.npos) {
+      // 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 (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:
+        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 {
+      return {ref_.IsLazyField(field),  //
+              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.
+  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 +3337,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 +3351,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 +3439,7 @@
  private:
   MetadataOwner() = default;  // private because singleton
 
-  WrappedMutex mu_;
+  absl::Mutex mu_;
   std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_;
 };
 
@@ -2981,7 +3450,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 +3545,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 +3556,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 +3633,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..3a6e93c 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 mamny 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..75ba3f6 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -42,25 +42,25 @@
 // 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/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 <gtest/gtest.h>
-#include <google/protobuf/map_test_util.h>
-#include <google/protobuf/test_util.h>
+#include "google/protobuf/map_test_util.h"
+#include "google/protobuf/test_util.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -1261,8 +1261,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 +1299,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..b5963a2 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:
@@ -120,6 +142,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 +197,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 +258,46 @@
     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) {}
     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;
+
+    const MessageLite* message_default() const {
+      return static_cast<const MessageLite*>(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 +308,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)
@@ -307,6 +386,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..f224d4c 100644
--- a/src/google/protobuf/generated_message_tctable_full.cc
+++ b/src/google/protobuf/generated_message_tctable_full.cc
@@ -30,24 +30,61 @@
 
 #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;
+  }
+
+  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..9d6a6da
--- /dev/null
+++ b/src/google/protobuf/generated_message_tctable_gen.cc
@@ -0,0 +1,826 @@
+// 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 if (field->is_repeated() && field->is_packed()) {
+      GOOGLE_LOG(DFATAL) << "Enum validation not handled: " << field->DebugString();
+      return;
+    } 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 (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.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.is_lazy || 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()) {
+    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 (cpp::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 (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:
+        // 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() &&
+            !cpp::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 (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() ||
+            options.is_implicitly_weak || options.is_lazy) {
+          handled = false;
+        } else {
+          handled = true;
+        }
+        break;
+
+      default:
+        handled = false;
+        break;
+    }
+    if (!handled) generated_fallback_fields.push_back(field);
+  }
+
+  return generated_fallback_fields;
+}
+
+std::vector<uint8_t> GenerateFieldNames(
+    const Descriptor* descriptor,
+    const std::vector<const FieldDescriptor*>& fields) {
+  static constexpr int kMaxNameLength = 255;
+  std::vector<uint8_t> 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* field : fields) {
+    out.push_back(field->name().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* field : fields) {
+    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.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.is_lazy) {
+          type_card |= fl::kRepLazy;
+        } else if (options.is_implicitly_weak) {
+          type_card |= fl::kRepIWeak;
+        }
+
+        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 second auxiliary entry.
+  if (!inlined_string_indices.empty()) {
+    aux_entries.resize(1);  // pad if necessary
+    aux_entries[0] = {kInlinedStringDonatedOffset};
+  }
+
+  // If this message is split, store the split pointer offset in the third
+  // auxiliary entry.
+  for (auto* field : ordered_fields) {
+    if (option_provider.GetForField(field).should_split) {
+      aux_entries.resize(3);  // pad if necessary
+      aux_entries[1] = {kSplitOffset};
+      aux_entries[2] = {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.is_implicitly_weak) {
+        // Implicit weak fields don't need to store a default instance pointer.
+      } else if (options.is_lazy) {
+        // Lazy fields are handled by the generated fallback function.
+      } else {
+        field_entries.back().aux_idx = aux_entries.size();
+        aux_entries.push_back(
+            {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);
+  field_name_data = GenerateFieldNames(descriptor, ordered_fields);
+
+  // 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..32e591d
--- /dev/null
+++ b/src/google/protobuf/generated_message_tctable_gen.h
@@ -0,0 +1,163 @@
+// 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 {
+
+// Helper class for generating tailcall parsing functions.
+struct PROTOBUF_EXPORT TailCallTableInfo {
+  struct PerFieldOptions {
+    bool is_lazy;
+    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,
+    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..490bbff74 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,
 
@@ -147,6 +166,10 @@
   // 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*
 };
 
 static_assert((kTvEnum & kTvRange) != 0,
@@ -175,7 +198,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 +206,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 +255,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 +274,15 @@
 // 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;
+  }
+
   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,6 +342,28 @@
   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 <typename FieldType, int data_offset, int hasbit_idx>
+  static constexpr TailCallParseFunc SingularVarintNoZag1() {
+    if (data_offset < 100) {
+      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)
@@ -337,6 +378,15 @@
   static const char* FastEvR1(PROTOBUF_TC_PARAM_DECL);
   static const char* FastEvR2(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* 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);
+
   // Functions referenced by generated fast tables (string types):
   //   B: bytes      S: string     U: UTF-8 string
   //   (empty): ArenaStringPtr     i: InlinedString
@@ -364,16 +414,26 @@
 
   // Functions referenced by generated fast tables (message types):
   //   M: message    G: group
+  //   d: default*   t: TcParseTable* (the contents of aux)
   //   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* 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,21 +478,30 @@
   // 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>
+  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 const char* FastEndGroupImpl(PROTOBUF_TC_PARAM_DECL);
+
   static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits(
       MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) {
     const uint32_t has_bits_offset = table->has_bits_offset;
     if (has_bits_offset) {
       // Only the first 32 has-bits are updated. Nothing above those is stored,
       // but e.g. messages without has-bits update the upper bits.
-      RefAt<uint32_t>(msg, has_bits_offset) = static_cast<uint32_t>(hasbits);
+      RefAt<uint32_t>(msg, has_bits_offset) |= static_cast<uint32_t>(hasbits);
     }
   }
 
@@ -497,8 +566,12 @@
   // 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, uint8_t min>
+  static inline const char* RepeatedEnumSmallRange(PROTOBUF_TC_PARAM_DECL);
 
   // Implementations for fast string field parsing functions:
   enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 };
@@ -507,11 +580,15 @@
   template <typename TagType, 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);
+
   // 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,7 +598,7 @@
   // 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);
@@ -531,23 +608,156 @@
   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);
 };
 
+template <typename FieldType, int data_offset, int hasbit_idx>
+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 nullptr;
+                    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..de9984c 100644
--- a/src/google/protobuf/generated_message_tctable_lite.cc
+++ b/src/google/protobuf/generated_message_tctable_lite.cc
@@ -30,17 +30,18 @@
 
 #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 "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"
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
@@ -66,78 +67,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 +225,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 +241,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);
@@ -318,36 +272,67 @@
   data.data = entry_offset << 32 | tag;
 
   using field_layout::FieldKind;
-  auto field_type = entry->type_card & FieldKind::kFkMask;
+  auto field_type =
+      entry->type_card & (+field_layout::kSplitMask | 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);
+      PROTOBUF_MUSTTAIL return MpVarint<false>(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);
+      PROTOBUF_MUSTTAIL return MpFixed<false>(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);
+      PROTOBUF_MUSTTAIL return MpString<false>(PROTOBUF_TC_PARAM_PASS);
     case FieldKind::kFkMessage:
-      PROTOBUF_MUSTTAIL return MpMessage(PROTOBUF_TC_PARAM_PASS);
+      PROTOBUF_MUSTTAIL return MpMessage<false>(PROTOBUF_TC_PARAM_PASS);
     case FieldKind::kFkMap:
       PROTOBUF_MUSTTAIL return MpMap(PROTOBUF_TC_PARAM_PASS);
+
+    case +field_layout::kSplitMask | FieldKind::kFkNone:
+      PROTOBUF_FALLTHROUGH_INTENDED;
+    case +field_layout::kSplitMask | FieldKind::kFkPackedVarint:
+      PROTOBUF_FALLTHROUGH_INTENDED;
+    case +field_layout::kSplitMask | FieldKind::kFkPackedFixed:
+      PROTOBUF_FALLTHROUGH_INTENDED;
+    case +field_layout::kSplitMask | FieldKind::kFkMap:
+      return Error(PROTOBUF_TC_PARAM_PASS);
+
+    case +field_layout::kSplitMask | FieldKind::kFkVarint:
+      PROTOBUF_MUSTTAIL return MpVarint<true>(PROTOBUF_TC_PARAM_PASS);
+    case +field_layout::kSplitMask | FieldKind::kFkFixed:
+      PROTOBUF_MUSTTAIL return MpFixed<true>(PROTOBUF_TC_PARAM_PASS);
+    case +field_layout::kSplitMask | FieldKind::kFkString:
+      PROTOBUF_MUSTTAIL return MpString<true>(PROTOBUF_TC_PARAM_PASS);
+    case +field_layout::kSplitMask | FieldKind::kFkMessage:
+      PROTOBUF_MUSTTAIL return MpMessage<true>(PROTOBUF_TC_PARAM_PASS);
     default:
       return Error(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;
+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);
 }
 
+const char* TcParser::FastEndG1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEndGroupImpl<uint8_t>(PROTOBUF_TC_PARAM_PASS);
+}
+const char* TcParser::FastEndG2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEndGroupImpl<uint16_t>(PROTOBUF_TC_PARAM_PASS);
+}
+
+namespace {
+
 // 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 +347,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 +358,145 @@
   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>(
+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>(
+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>(
+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>(
+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) {
+const char* TcParser::FastMtS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, false, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastMtS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, false, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastGtS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, true, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastGtS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, true, true>(
+      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>(
+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>(
+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>(
+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>(
+const char* TcParser::FastGdR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, true, false>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastMtR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, false, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastMtR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, false, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastGtR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, true, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastGtR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, true, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
@@ -498,7 +554,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);
@@ -768,7 +824,13 @@
     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 then, the effect of declaring it "volatile".
+  asm("" : "+m"(spill));
+#endif
 
   uint64_t tmp;
   PROTOBUF_ASSUME(static_cast<int8_t>(*ptr) < 0);
@@ -788,8 +850,31 @@
 }
 
 const char* TcParser::FastV8S1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularVarint<bool, uint8_t>(
-      PROTOBUF_TC_PARAM_PASS);
+  // 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());
+    // 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 += 2;  // Consume the tag and the value.
+    hasbits |= (uint64_t{1} << data.hasbit_idx());
+
+    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);
 }
 const char* TcParser::FastV8S2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<bool, uint16_t>(
@@ -842,7 +927,7 @@
     }
   }
   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;
@@ -977,10 +1062,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.
@@ -1047,7 +1128,7 @@
     }
   }
   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
@@ -1089,13 +1170,98 @@
       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);
+}
+
+const char* TcParser::FastEr0S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnumSmallRange<uint8_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastEr0S2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnumSmallRange<uint16_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastEr1S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnumSmallRange<uint8_t, 1>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+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>
+PROTOBUF_ALWAYS_INLINE 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) {
+      // Packed parsing is handled by generated fallback.
+      PROTOBUF_MUSTTAIL return FastUnknownEnumFallback(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);
+}
+
+const char* TcParser::FastEr0R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<uint8_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+const char* TcParser::FastEr0R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<uint16_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+const char* TcParser::FastEr1R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<uint8_t, 1>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+const char* TcParser::FastEr1R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<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,
@@ -1128,7 +1294,7 @@
   ptr += sizeof(TagType);
   hasbits |= (uint64_t{1} << data.hasbit_idx());
   auto& field = RefAt<ArenaStringPtr>(msg, data.offset());
-  auto arena = ctx->data().arena;
+  auto arena = msg->GetArenaForAllocation();
   if (arena) {
     ptr = ctx->ReadArenaString(ptr, &field, arena);
   } else {
@@ -1203,31 +1369,52 @@
   if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
     PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
   }
-  auto expected_tag = UnalignedLoad<TagType>(ptr);
+  const 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 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(
+                IsStructurallyValidUTF8(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);
 }
 
@@ -1261,20 +1448,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 +1466,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;
 
@@ -1326,7 +1504,7 @@
       case field_layout::kRepGroup:
       case field_layout::kRepIWeak: {
         auto& field = RefAt<MessageLite*>(msg, current_entry->offset);
-        if (!ctx->data().arena) {
+        if (!msg->GetArenaForAllocation()) {
           delete field;
         }
         break;
@@ -1340,6 +1518,39 @@
   return true;
 }
 
+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>
 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;
@@ -1364,16 +1575,17 @@
   }
   // 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);
@@ -1458,6 +1670,7 @@
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
+template <bool is_split>
 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;
@@ -1501,18 +1714,19 @@
   // 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);
@@ -1631,7 +1845,7 @@
   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) {
@@ -1653,6 +1867,7 @@
   return true;
 }
 
+template <bool is_split>
 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;
@@ -1676,17 +1891,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,6 +1925,19 @@
   return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
 }
 
+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;
+}
+
 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;
@@ -1726,18 +1955,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,6 +2001,7 @@
   return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
 }
 
+template <bool is_split>
 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;
@@ -1789,21 +2040,33 @@
   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) {
+      field = table->field_aux(&entry)->message_default()->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,15 +2100,24 @@
   }
 
   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);
+  if ((type_card & field_layout::kTvMask) == field_layout::kTvTable) {
+    auto* inner_table = table->field_aux(&entry)->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 {
+    auto& field = RefAt<RepeatedPtrFieldBase>(msg, entry.offset);
+    MessageLite* value = field.Add<GenericTypeHandler<MessageLite>>(
+        table->field_aux(&entry)->message_default());
+    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) {
diff --git a/src/google/protobuf/generated_message_tctable_lite_test.cc b/src/google/protobuf/generated_message_tctable_lite_test.cc
index 4310803..79b0d46 100644
--- a/src/google/protobuf/generated_message_tctable_lite_test.cc
+++ b/src/google/protobuf/generated_message_tctable_lite_test.cc
@@ -30,8 +30,8 @@
 
 #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 "google/protobuf/wire_format_lite.h"
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
@@ -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..f9c75c6 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/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"
 
 // 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..1915e8c 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/io/coded_stream.h"
+#include "google/protobuf/arena.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..53552df 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/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.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/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..f53c612
--- /dev/null
+++ b/src/google/protobuf/io/BUILD.bazel
@@ -0,0 +1,184 @@
+# 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",
+    ],
+)
+
+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_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..b29fccf 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
@@ -964,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/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index c8fc994..d849a1b 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
@@ -1061,6 +1060,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.
@@ -1288,7 +1289,6 @@
   // 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 ====================================================
@@ -1729,15 +1729,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 +1746,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 +1779,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 +1796,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..1fca15c 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,19 @@
 #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/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 +71,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 +94,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 +113,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 +136,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 +727,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 +1318,7 @@
   int backup_amount_;
 
  private:
-  char buffer_[1024];
+  char buffer_[1024] = {};
   int64_t buffer_count_;
 };
 
@@ -1345,4 +1347,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..c7ef132 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,6 +74,8 @@
   // 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);
+  GzipInputStream(const GzipInputStream&) = delete;
+  GzipInputStream& operator=(const GzipInputStream&) = delete;
   virtual ~GzipInputStream();
 
   // Return last error message or NULL if no error.
@@ -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,6 +141,8 @@
 
   // 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();
 
@@ -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..c4d1847 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -32,195 +32,235 @@
 //  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/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/stubs/stringprintf.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 {
+namespace {
+// Returns the number of spaces stripped.
+size_t ConsumeInitialRawStringIndent(absl::string_view& format) {
+  size_t len = 0;
+  // We are processing a call that looks like
+  //
+  // p->Emit(R"cc(
+  //   class Foo {
+  //     int x, y, z;
+  //   };
+  // )cc");
+  //
+  // We need to discard all leading newlines, then consume all spaces until
+  // we reach a non-space; this run of spaces is stripped off at the start of
+  // each line.
 
-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_);
+  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_ += "  "; }
+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<std::pair<
+        absl::string_view, absl::variant<std::string, std::function<void()>>>>
+        vars,
+    absl::string_view format, SourceLocation loc) {
+  PrintOptions opts;
+  opts.strip_raw_string_indentation = true;
+  opts.loc = loc;
+
+  absl::flat_hash_map<absl::string_view,
+                      absl::variant<std::string, std::function<void()>>>
+      map;
+  map.reserve(vars.size());
+  for (auto& var : vars) {
+    auto result = map.insert(var);
+    GOOGLE_CHECK(result.second) << "repeated variable in Emit() call: \"" << var.first
+                         << "\"";
+  }
+
+  var_lookups_.emplace_back([&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 *str;
+    }
+
+    auto* f = absl::get_if<std::function<void()>>(&it->second);
+    GOOGLE_CHECK(f != nullptr);
+    return *f;
+  });
+
+  PrintImpl(format, {}, opts);
+
+  var_lookups_.pop_back();
+}
+
+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 +269,389 @@
   // 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(StringPrintf("%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 StringPrintf("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 StringPrintf(
+                "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
+                                     ? ConsumeInitialRawStringIndent(format)
+                                     : 0;
+
+  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_substitions && 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 StringPrintf(
+                  "_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");
+
+      IndentIfAtStart();
+      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 ; 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$/**/;
+      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 StringPrintf(
+        "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..3c096a4 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -37,27 +37,40 @@
 #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 "absl/cleanup/cleanup.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/functional/function_ref.h"
+#include "google/protobuf/stubs/stringprintf.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"
+#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 {
 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 +80,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 +110,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 +119,185 @@
   }
 
  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.
+//
+// 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.
+//
+// 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.
+//
+// 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 +369,249 @@
 //
 // 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);
+    }
+  };
+
  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(std::string(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(std::string(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 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(std::string(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(std::string(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_indentation.
+  //
+  // 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<
+          std::pair<absl::string_view,
+                    // NOTE: This is a std::string, not a string_view, to work
+                    // around an MSVC bug(?) that causes temporary strings
+                    // passed into this function to be destroyed early.
+                    absl::variant<std::string, std::function<void()>>>>
+          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_substitions = 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<std::string, std::string> map;
+    map.reserve(sizeof...(args) / 2);
+    for (size_t i = 0; i < sizeof...(args); i += 2) {
+      map.emplace(std::string(vars[i]), std::string(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 +620,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 +633,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 +641,138 @@
   // 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,
+  // compiler::cpp::Formatter instead.
+  void FormatInternal(absl::Span<const std::string> args,
                       const std::map<std::string, std::string>& vars,
-                      const char* format);
+                      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_substitions = 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_;
+  // 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);
 
-  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_;
+  google::protobuf::io::zc_sink_internal::ZeroCopyStreamByteSink sink_;
+  Options options_;
+  size_t indent_ = 0;
+  bool at_start_of_line_ = true;
+  bool failed_ = false;
 
-  std::string indent_;
-  bool at_start_of_line_;
-  bool failed_;
+  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);
 };
-
 }  // 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..7e1ebaf 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,306 @@
   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, EmitWithSubs) {
   {
-    // 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({{"class", "Foo"}, {"f1", "x"}, {"f2", "y"}, {"f3", "z"}},
+                 R"cc(
+                   class $class$ {
+                     int $f1$, $f2$, $f3$;
+                   };
+                 )cc");
   }
-#ifdef PROTOBUF_HAS_DEATH_TEST
-  // Death tests in case of illegal format strings.
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z;\n"
+            "};\n");
+}
+
+TEST_F(PrinterTest, EmitWithVars) {
   {
-    // Unused arguments
-    std::string s;
-    StringOutputStream output(&s);
-    Printer printer(&output, '$');
-    EXPECT_DEATH(printer.FormatInternal(args, vars, "$empty $$1$"), "Unused");
+    Printer printer(output());
+    auto v = printer.WithVars({
+        {"class", "Foo"},
+        {"f1", "x"},
+        {"f2", "y"},
+        {"f3", "z"},
+    });
+    printer.Emit(R"cc(
+      class $class$ {
+        int $f1$, $f2$, $f3$;
+      };
+    )cc");
   }
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z;\n"
+            "};\n");
+}
+
+TEST_F(PrinterTest, EmitWithSpacedVars) {
   {
-    // 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({
+        {"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) {
   {
-    // 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.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;
   {
-    // 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(), '$', &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;
   {
-    // 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);
+    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");
   }
+
+  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;
   {
-    // Illegal variable
-    std::string s;
-    StringOutputStream output(&s);
-    Printer printer(&output, '$');
-    EXPECT_DEATH(printer.FormatInternal({}, vars, "$ $"), "Empty");
+    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");
   }
-#endif  // PROTOBUF_HAS_DEATH_TEST
+
+  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..61c6c29 100644
--- a/src/google/protobuf/io/strtod.cc
+++ b/src/google/protobuf/io/strtod.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/io/strtod.h>
+#include "google/protobuf/io/strtod.h"
 
 #include <cstdio>
 #include <cstring>
 #include <limits>
 #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 <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/strutil.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index f9e0776..7bc0820 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -88,18 +88,18 @@
 // 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 "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"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -406,7 +406,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();
@@ -1024,7 +1024,7 @@
          static_cast<size_t>(end - start) != text.size() || *start == '-')
       << " Tokenizer::ParseFloat() passed text that could not have been"
          " tokenized as a float: "
-      << CEscape(text);
+      << absl::CEscape(text);
   return result;
 }
 
@@ -1145,7 +1145,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;
   }
 
@@ -1236,4 +1236,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..cab1faf 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.
@@ -276,8 +277,6 @@
 
   // -----------------------------------------------------------------
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
-
   Token current_;   // Returned by current().
   Token previous_;  // Returned by previous().
 
@@ -423,9 +422,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 +436,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..40a24c8 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[] = {
@@ -796,7 +796,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]);
   }
@@ -1058,7 +1058,7 @@
 };
 
 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[] = {
@@ -1067,7 +1067,8 @@
     {"'\\X' foo", true, "0:2: Invalid escape sequence in string literal.\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/stubs/statusor.cc b/src/google/protobuf/io/zero_copy_sink.cc
similarity index 67%
copy from src/google/protobuf/stubs/statusor.cc
copy to src/google/protobuf/io/zero_copy_sink.cc
index 9c0a178..7045648 100644
--- a/src/google/protobuf/stubs/statusor.cc
+++ b/src/google/protobuf/io/zero_copy_sink.cc
@@ -28,21 +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/stubs/statusor.h>
+#include "google/protobuf/io/zero_copy_sink.h"
 
-#include <google/protobuf/stubs/logging.h>
+#include <algorithm>
+#include <cstddef>
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace statusor_internal {
+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);
+    }
 
-void StatusOrHelper::Crash(const Status& status) {
-  GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
-                    << status.ToString();
+    auto to_write = std::min(len, buffer_size_);
+    memcpy(buffer_, bytes, to_write);
+
+    buffer_ = static_cast<char*>(buffer_) + to_write;
+    buffer_size_ -= to_write;
+
+    bytes += to_write;
+    len -= to_write;
+
+    bytes_written_ += to_write;
+  }
 }
-
-}  // namespace statusor_internal
-}  // namespace util
+}  // 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..4d70d39
--- /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/stubs/bytestream.h"
+#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 strings::ByteSink {
+ public:
+  explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream)
+      : stream_(stream) {}
+  ZeroCopyStreamByteSink(const ZeroCopyStreamByteSink&) = delete;
+  ZeroCopyStreamByteSink& operator=(const ZeroCopyStreamByteSink&) = delete;
+
+  ~ZeroCopyStreamByteSink() override {
+    if (buffer_size_ > 0) {
+      stream_->BackUp(buffer_size_);
+    }
+  }
+
+  void Append(const char* bytes, size_t len) override;
+  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..83b7225 100644
--- a/src/google/protobuf/io/zero_copy_stream.cc
+++ b/src/google/protobuf/io/zero_copy_stream.cc
@@ -32,10 +32,10 @@
 //  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 "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/io/zero_copy_stream.h b/src/google/protobuf/io/zero_copy_stream.h
index 2041cbf..ad27345 100644
--- a/src/google/protobuf/io/zero_copy_stream.h
+++ b/src/google/protobuf/io/zero_copy_stream.h
@@ -107,12 +107,12 @@
 #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 "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 +127,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 +183,6 @@
   // Returns the total number of bytes read since this object was created.
   virtual int64_t ByteCount() const = 0;
 
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
 };
 
 // Abstract interface similar to an output stream but designed to minimize
@@ -191,6 +190,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 +247,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..2955c7b 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -43,11 +43,11 @@
 #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"
+#include "google/protobuf/stubs/stl_util.h"
 
 
 namespace google {
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..9becd2c 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,19 @@
 //  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/internal/resize_uninitialized.h"
+
+// Must be included last
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -154,7 +158,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 +187,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;
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..28ad9d6 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,20 @@
 #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"
+#include "google/protobuf/stubs/stl_util.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -78,6 +79,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 +98,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 +116,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 +133,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 +153,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 +166,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 +222,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 +266,6 @@
   // BackUp().  These need to be returned again.
   // 0 <= backup_bytes_ <= buffer_used_
   int backup_bytes_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
 };
 
 // ===================================================================
@@ -298,6 +307,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 +355,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,6 +367,10 @@
   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;
@@ -367,8 +382,6 @@
   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);
 };
 
 
@@ -408,6 +421,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..d82354e 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -61,21 +61,22 @@
 
 #include <memory>
 #include <sstream>
+#include <utility>
 
-#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/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"
 
 #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>
 
 namespace google {
@@ -139,7 +140,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 +571,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));
 
@@ -1024,7 +1025,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 +1053,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/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..529e7bd 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 "google/protobuf/map_lite_unittest.pb.h"
+#include "google/protobuf/unittest_lite.pb.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 "google/protobuf/stubs/strutil.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/parse_context.h"
+#include "google/protobuf/test_util_lite.h"
+#include "google/protobuf/wire_format_lite.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/map.cc b/src/google/protobuf/map.cc
index d60a9a2..1d7535d 100644
--- a/src/google/protobuf/map.cc
+++ b/src/google/protobuf/map.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/map.h>
+#include "google/protobuf/map.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 008c192..9f7c200 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -55,19 +55,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 {
@@ -333,6 +333,11 @@
 
 }  // 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 +368,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 +385,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 +428,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
@@ -466,6 +489,9 @@
           table_(const_cast<void**>(internal::kGlobalEmptyTable)),
           alloc_(arena) {}
 
+    InnerMap(const InnerMap&) = delete;
+    InnerMap& operator=(const InnerMap&) = delete;
+
     ~InnerMap() {
       if (alloc_.arena() == nullptr &&
           num_buckets_ != internal::kGlobalEmptyTableSize) {
@@ -1181,7 +1207,6 @@
     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>
@@ -1270,7 +1295,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 +1375,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 +1437,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,7 +1448,7 @@
     }
   }
 
-  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.
@@ -1428,6 +1460,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_;
 
@@ -1443,6 +1492,6 @@
 }  // 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..78ed4f2 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/io/coded_stream.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/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
@@ -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_);
@@ -429,8 +433,6 @@
   template <typename C, typename K, typename V, WireFormatLite::FieldType,
             WireFormatLite::FieldType>
   friend class internal::MapFieldLite;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
 };
 
 template <typename T, typename Key, typename Value,
@@ -443,14 +445,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 +559,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..d8e539c 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/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"
 
 // 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()) {
@@ -105,7 +105,7 @@
     }
   }
   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 +204,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..d0116bd 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -32,21 +32,21 @@
 #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/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 <gtest/gtest.h>
-#include <google/protobuf/arena_test_util.h>
-#include <google/protobuf/map_test_util.h>
+#include "google/protobuf/arena_test_util.h"
+#include "google/protobuf/map_test_util.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
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_test.cc b/src/google/protobuf/map_test.cc
index f7c024c..4eee747 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.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_proto2_unittest.pb.h>
-#include <google/protobuf/map_unittest.pb.h>
-#include <google/protobuf/reflection_tester.h>
-#include <google/protobuf/test_util2.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/test_util2.h"
 
 
 #define BRIDGE_UNITTEST ::google::protobuf::bridge_unittest
@@ -41,13 +41,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 +84,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..baf3c82 100644
--- a/src/google/protobuf/map_test.inc
+++ b/src/google/protobuf/map_test.inc
@@ -46,36 +46,36 @@
 #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/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 =====================================================
 
@@ -737,6 +738,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 +811,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() {}
@@ -1393,7 +1488,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 +1611,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 +1648,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 +1685,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 +1841,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 +1882,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));
@@ -1917,7 +2012,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 +2167,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 +2182,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 +2526,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);
@@ -2938,7 +3033,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;
@@ -3689,7 +3784,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 +3844,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 +3886,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 +3902,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 +3921,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 +4161,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..130e494 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -31,14 +31,14 @@
 #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"
 
 #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 c210c63d..c092792 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/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"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 6cdc6c8..4cad7af 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -32,40 +32,43 @@
 //  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 "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.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/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/stl_util.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 +78,7 @@
 
 }  // namespace internal
 
+using internal::DownCast;
 using internal::ReflectionOps;
 using internal::WireFormat;
 using internal::WireFormatLite;
@@ -92,7 +96,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 +156,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 +171,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 +225,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 +244,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 +255,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 +317,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 +332,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 +340,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 +351,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 +359,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 +459,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..fd03c6b 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -116,19 +116,23 @@
 #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/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"
@@ -157,6 +161,7 @@
 class MapFieldBase;
 class SwapFieldHelper;
 class CachedSize;
+struct TailCallTableInfo;
 }  // namespace internal
 class UnknownFieldSet;  // unknown_field_set.h
 namespace io {
@@ -203,12 +208,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 +245,8 @@
 class PROTOBUF_EXPORT Message : public MessageLite {
  public:
   constexpr Message() {}
+  Message(const Message&) = delete;
+  Message& operator=(const Message&) = delete;
 
   // Basic Operations ------------------------------------------------
 
@@ -298,6 +305,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")
@@ -400,12 +411,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 +472,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 +493,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;
 
@@ -1029,6 +1051,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 +1069,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;
@@ -1174,6 +1225,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 +1256,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 +1321,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 +1387,6 @@
   static void InternalRegisterGeneratedMessage(const Descriptor* descriptor,
                                                const Message* prototype);
 
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory);
 };
 
 #define DECLARE_GET_REPEATED_FIELD(TYPE)                           \
@@ -1372,7 +1433,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 +1542,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..7cae7be 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -33,28 +33,32 @@
 //  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/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 "absl/base/dynamic_annotations.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/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 {
@@ -65,7 +69,7 @@
 
 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 +116,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 +140,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 +182,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 +309,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 +325,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 +455,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 +571,7 @@
   }
 
   std::vector<std::pair<void (*)(const void*), const void*>> functions;
-  Mutex mutex;
+  absl::Mutex mutex;
 };
 
 static void RunZeroArgFunc(const void* arg) {
@@ -580,7 +585,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 +604,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..f4bca9c 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/io/coded_stream.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/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,6 +169,8 @@
 class PROTOBUF_EXPORT MessageLite {
  public:
   constexpr MessageLite() {}
+  MessageLite(const MessageLite&) = delete;
+  MessageLite& operator=(const MessageLite&) = delete;
   virtual ~MessageLite() = default;
 
   // 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..1217c40 100644
--- a/src/google/protobuf/message_unittest.inc
+++ b/src/google/protobuf/message_unittest.inc
@@ -40,31 +40,33 @@
 #include <sys/types.h>
 
 #include <cmath>
+#include <functional>
 #include <limits>
+#include <vector>
 
-#include <google/protobuf/message.h>
+#include "google/protobuf/message.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 +126,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 +139,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 +257,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 +287,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 +450,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 +1174,261 @@
             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) {
+  uint8_t buf[100];
+  uint8_t* p = buf;
+
+  p = internal::WireFormatLite::WriteEnumToArray(number, value, p);
+  p = AddNonCanonicalBytes(buf, p, non_canonical_bytes);
+  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_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;
+        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);
+          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)));
+        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);
+      }
+    }
+  }
+}
+
+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);
+          }
+        }
+    }
+  }
+}
+
 }  // 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..d28fb14 100644
--- a/src/google/protobuf/no_field_presence_test.cc
+++ b/src/google/protobuf/no_field_presence_test.cc
@@ -30,10 +30,10 @@
 
 #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/unittest.pb.h"
+#include "google/protobuf/unittest_no_field_presence.pb.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/descriptor.h"
 #include <gtest/gtest.h>
 
 namespace google {
diff --git a/src/google/protobuf/parse_context.cc b/src/google/protobuf/parse_context.cc
index 59852fd..3406319 100644
--- a/src/google/protobuf/parse_context.cc
+++ b/src/google/protobuf/parse_context.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/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 "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 "absl/strings/string_view.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 {
@@ -279,7 +279,8 @@
 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;
+  ptr = msg->_InternalParse(ptr, this);
   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,11 +377,11 @@
 }
 
 // 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) {
+bool VerifyUTF8(absl::string_view str, const char* field_name) {
   if (!IsStructurallyValidUTF8(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(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..3dbdf3e 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/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream.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/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;
@@ -387,7 +399,6 @@
   struct Data {
     const DescriptorPool* pool = nullptr;
     MessageFactory* factory = nullptr;
-    Arena* arena = nullptr;
   };
 
   template <typename... T>
@@ -427,6 +438,17 @@
                                     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);
+    ptr = ptr ? TcParser::ParseLoop(msg, ptr, this, table) : nullptr;
+    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) {
@@ -439,6 +461,18 @@
     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_++;
+    ptr = TcParser::ParseLoop(msg, ptr, this, table);
+    group_depth_--;
+    depth_++;
+    if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr;
+    return ptr;
+  }
+
  private:
   // Out-of-line routine to save space in ParseContext::ParseMessage<T>
   //   int old;
@@ -451,6 +485,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 +573,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 +672,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 +832,26 @@
                                                           const char* ptr) {
   int old;
   ptr = ReadSizeAndPushLimitAndDepth(ptr, &old);
-  ptr = ptr ? msg->_InternalParse(ptr, this) : nullptr;
+  if (ptr == nullptr) return ptr;
+  ptr = msg->_InternalParse(ptr, this);
   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,
@@ -867,7 +964,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 +1117,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 8943a44..0d6db17 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -139,6 +139,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 +154,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 +181,33 @@
 // 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
+
+// Used to escape C++20 keywords.
+// TODO(mkruskal): ping b/238664698 when this lands in opensource.
+// Owner: mkruskal@
+#define PROTOBUF_FUTURE_CPP20_KEYWORDS 1
+#else
 #define PROTOBUF_FUTURE_FINAL
+#endif
 
 #ifdef PROTOBUF_VERSION
 #error PROTOBUF_VERSION was previously defined
@@ -356,15 +390,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 +552,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 +668,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
@@ -772,8 +814,8 @@
 #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.
+// PROTOBUF_EXPERIMENTAL_USE_TAIL_CALL_TABLE_PARSER at compilation time.
+// We hope to turn on table-driven parsing by default in Q4 2022.
 #ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED
 #error PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED was previously declared
 #endif
@@ -781,11 +823,29 @@
 #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 +861,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 +903,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 +941,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 +955,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)
@@ -903,6 +993,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..e991502 100644
--- a/src/google/protobuf/port_undef.inc
+++ b/src/google/protobuf/port_undef.inc
@@ -38,7 +38,9 @@
 #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 +55,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 +73,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 +102,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 +168,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)
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 7e6bbf1..64d8247 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.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/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/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 <gtest/gtest.h>
 
 namespace google {
diff --git a/src/google/protobuf/proto3_arena_lite_unittest.cc b/src/google/protobuf/proto3_arena_lite_unittest.cc
index 06b8d08..7c37f3f 100644
--- a/src/google/protobuf/proto3_arena_lite_unittest.cc
+++ b/src/google/protobuf/proto3_arena_lite_unittest.cc
@@ -32,9 +32,8 @@
 #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/unittest_proto3_arena.pb.h"
+#include "google/protobuf/arena.h"
 #include <gtest/gtest.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..175c6e9 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/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 <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/test_util.h>
+#include "google/protobuf/stubs/strutil.h"
+#include "google/protobuf/test_util.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;
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..3fdee89 100644
--- a/src/google/protobuf/reflection_internal.h
+++ b/src/google/protobuf/reflection_internal.h
@@ -31,9 +31,9 @@
 #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 "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..282e4ae 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/unittest.pb.h"
+#include "google/protobuf/descriptor.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/test_util.h>
+#include "google/protobuf/test_util.h"
 
-#include <google/protobuf/stubs/strutil.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..f8212e3 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -32,15 +32,15 @@
 //  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 <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -68,4 +68,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..ccae6bb 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 = 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..ccecdd0 100644
--- a/src/google/protobuf/repeated_field_reflection_unittest.cc
+++ b/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -33,25 +33,26 @@
 // 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/unittest.pb.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 "google/protobuf/port.h"
+#include "google/protobuf/test_util.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 +114,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 +122,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 +134,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 +294,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 +303,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..eb0b909 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 "google/protobuf/unittest.pb.h"
+#include "google/protobuf/stubs/strutil.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/str_cat.h"
+#include "google/protobuf/stubs/stl_util.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) {
@@ -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().
@@ -2277,11 +2334,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 +2371,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 +2417,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..f58481d 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*,
@@ -1083,7 +1144,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 +1159,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 +1202,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 +1336,7 @@
 }
 
 template <typename Element>
-inline Element* RepeatedPtrField<Element>::Add() {
+PROTOBUF_NOINLINE Element* RepeatedPtrField<Element>::Add() {
   return RepeatedPtrFieldBase::Add<TypeHandler>();
 }
 
@@ -1505,7 +1571,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 +1581,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) {
@@ -1965,6 +2031,6 @@
 }  // 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..e6934f0 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -46,6 +46,8 @@
   ~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) = {
@@ -64,7 +66,7 @@
   "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;
+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,
     "google/protobuf/source_context.proto",
@@ -294,4 +296,4 @@
 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 e9c41bd..ee4e6b2 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,19 +19,19 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -159,7 +159,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:
@@ -242,11 +242,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() {
@@ -255,9 +255,9 @@
 }
 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
@@ -278,5 +278,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh
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..42fbd1a 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -84,6 +84,8 @@
   ~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,
@@ -94,6 +96,8 @@
   ~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_),
@@ -101,6 +105,8 @@
   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,
@@ -114,13 +120,15 @@
   ~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)},
+  { 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[] = {
@@ -148,7 +156,7 @@
   "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;
+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,
     "google/protobuf/struct.proto",
@@ -411,6 +419,8 @@
 
 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);
 };
@@ -593,7 +603,7 @@
       // .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);
+          uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_null_value(static_cast<::PROTOBUF_NAMESPACE_ID::NullValue>(val));
         } else
@@ -1054,4 +1064,4 @@
 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 ac2d971..e52be94 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,23 +19,23 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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>
+#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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fstruct_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -86,11 +86,15 @@
   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);
+  return NullValue_Name(static_cast<NullValue>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, NullValue* value) {
+    ::absl::string_view name, NullValue* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<NullValue>(
     NullValue_descriptor(), name, value);
 }
@@ -225,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.Struct";
   }
   protected:
@@ -398,7 +402,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:
@@ -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:
@@ -1173,5 +1177,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto_2epb_2eh
diff --git a/src/google/protobuf/stubs/BUILD.bazel b/src/google/protobuf/stubs/BUILD.bazel
new file mode 100644
index 0000000..15db8bf
--- /dev/null
+++ b/src/google/protobuf/stubs/BUILD.bazel
@@ -0,0 +1,117 @@
+# 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 = [
+        "bytestream.cc",
+        "common.cc",
+        "stringprintf.cc",
+        "structurally_valid.cc",
+        "strutil.cc",
+    ],
+    hdrs = [
+        "bytestream.h",
+        "callback.h",
+        "common.h",
+        "logging.h",
+        "mathutil.h",
+        "platform_macros.h",
+        "port.h",
+        "status_macros.h",
+        "stl_util.h",
+        "stringprintf.h",
+        "strutil.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 = [
+        "bytestream.h",
+        "callback.h",
+        "common.h",
+        "logging.h",
+        "mathutil.h",
+        "platform_macros.h",
+        "port.h",
+        "status_macros.h",
+        "stl_util.h",
+        "stringprintf.h",
+        "strutil.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 = [
+        "bytestream_unittest.cc",
+        "common_unittest.cc",
+        "stringprintf_unittest.cc",
+        "structurally_valid_unittest.cc",
+        "strutil_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
index 980d6f6..9a516d6 100644
--- a/src/google/protobuf/stubs/bytestream.cc
+++ b/src/google/protobuf/stubs/bytestream.cc
@@ -28,12 +28,13 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <google/protobuf/stubs/bytestream.h>
+#include "google/protobuf/stubs/bytestream.h"
 
 #include <string.h>
+
 #include <algorithm>
 
-#include <google/protobuf/stubs/logging.h>
+#include "google/protobuf/stubs/logging.h"
 
 namespace google {
 namespace protobuf {
@@ -41,7 +42,7 @@
 
 void ByteSource::CopyTo(ByteSink* sink, size_t n) {
   while (n > 0) {
-    StringPiece fragment = Peek();
+    absl::string_view fragment = Peek();
     if (fragment.empty()) {
       GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input.";
       break;
@@ -149,9 +150,7 @@
   return input_.size();
 }
 
-StringPiece ArrayByteSource::Peek() {
-  return input_;
-}
+absl::string_view ArrayByteSource::Peek() { return input_; }
 
 void ArrayByteSource::Skip(size_t n) {
   GOOGLE_DCHECK_LE(n, input_.size());
@@ -172,9 +171,9 @@
   return available;
 }
 
-StringPiece LimitByteSource::Peek() {
-  StringPiece piece = source_->Peek();
-  return StringPiece(piece.data(), std::min(piece.size(), limit_));
+absl::string_view LimitByteSource::Peek() {
+  absl::string_view piece = source_->Peek();
+  return absl::string_view(piece.data(), std::min(piece.size(), limit_));
 }
 
 void LimitByteSource::Skip(size_t n) {
diff --git a/src/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h
index c7a48de..a11233e 100644
--- a/src/google/protobuf/stubs/bytestream.h
+++ b/src/google/protobuf/stubs/bytestream.h
@@ -44,19 +44,21 @@
 //      NullByteSink            Consumes a never-ending stream of bytes
 //
 //   ByteSource:
-//      ArrayByteSource         Reads from an array or string/StringPiece
+//      ArrayByteSource         Reads from an array or string
 //      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 "absl/strings/string_view.h"
+#include "google/protobuf/stubs/common.h"
 
-#include <google/protobuf/port_def.inc>
+// Must be last.
+#include "google/protobuf/port_def.inc"  // NOLINT
 
 class CordByteSink;
 
@@ -78,6 +80,8 @@
 class PROTOBUF_EXPORT ByteSink {
  public:
   ByteSink() {}
+  ByteSink(const ByteSink&) = delete;
+  ByteSink& operator=(const ByteSink&) = delete;
   virtual ~ByteSink() {}
 
   // Appends the "n" bytes starting at "bytes".
@@ -87,9 +91,6 @@
   // 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
@@ -99,7 +100,7 @@
 //
 //   ByteSource* source = ...
 //   while (source->Available() > 0) {
-//     StringPiece data = source->Peek();
+//     absl::string_view data = source->Peek();
 //     ... do something with "data" ...
 //     source->Skip(data.length());
 //   }
@@ -107,6 +108,8 @@
 class PROTOBUF_EXPORT ByteSource {
  public:
   ByteSource() {}
+  ByteSource(const ByteSource&) = delete;
+  ByteSource& operator=(const ByteSource&) = delete;
   virtual ~ByteSource() {}
 
   // Returns the number of bytes left to read from the source. Available()
@@ -118,17 +121,18 @@
   //       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.
+  // Returns an absl::string_view 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;
+  // The length of the returned absl::string_view will be <= Available().
+  virtual absl::string_view Peek() = 0;
 
-  // Skips the next n bytes. Invalidates any StringPiece returned by a previous
-  // call to Peek().
+  // Skips the next n bytes. Invalidates any absl::string_view returned by a
+  // previous call to Peek().
   //
   // REQUIRES: Available() >= n
   virtual void Skip(size_t n) = 0;
@@ -140,9 +144,6 @@
   //
   // REQUIRES: Available() >= n
   virtual void CopyTo(ByteSink* sink, size_t n);
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource);
 };
 
 //
@@ -162,6 +163,8 @@
 //
 class PROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink {
  public:
+  UncheckedArrayByteSink(const UncheckedArrayByteSink&) = delete;
+  UncheckedArrayByteSink& operator=(const UncheckedArrayByteSink&) = delete;
   explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {}
   virtual void Append(const char* data, size_t n) override;
 
@@ -173,7 +176,6 @@
 
  private:
   char* dest_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink);
 };
 
 // Implementation of ByteSink that writes to a sized byte array. This sink will
@@ -191,6 +193,8 @@
 class PROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink {
  public:
   CheckedArrayByteSink(char* outbuf, size_t capacity);
+  CheckedArrayByteSink(const CheckedArrayByteSink&) = delete;
+  CheckedArrayByteSink& operator=(const CheckedArrayByteSink&) = delete;
   virtual void Append(const char* bytes, size_t n) override;
 
   // Returns the number of bytes actually written to the sink.
@@ -205,7 +209,6 @@
   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)
@@ -227,6 +230,8 @@
 class PROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink {
  public:
   explicit GrowingArrayByteSink(size_t estimated_size);
+  GrowingArrayByteSink(const GrowingArrayByteSink&) = delete;
+  GrowingArrayByteSink& operator=(const GrowingArrayByteSink&) = delete;
   virtual ~GrowingArrayByteSink();
   virtual void Append(const char* bytes, size_t n) override;
 
@@ -241,7 +246,6 @@
   size_t capacity_;
   char* buf_;
   size_t size_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink);
 };
 
 // Implementation of ByteSink that appends to the given string.
@@ -257,11 +261,12 @@
 class PROTOBUF_EXPORT StringByteSink : public ByteSink {
  public:
   explicit StringByteSink(std::string* dest) : dest_(dest) {}
+  StringByteSink(const StringByteSink&) = delete;
+  StringByteSink& operator=(const StringByteSink&) = delete;
   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.
@@ -274,17 +279,16 @@
 class PROTOBUF_EXPORT NullByteSink : public ByteSink {
  public:
   NullByteSink() {}
+  NullByteSink(const NullByteSink&) = delete;
+  NullByteSink& operator=(const NullByteSink&) = delete;
   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.
+// Implementation of ByteSource that reads from an absl::string_view.
 //
 // Example:
 //
@@ -295,15 +299,16 @@
 //
 class PROTOBUF_EXPORT ArrayByteSource : public ByteSource {
  public:
-  explicit ArrayByteSource(StringPiece s) : input_(s) {}
+  explicit ArrayByteSource(absl::string_view s) : input_(s) {}
+  ArrayByteSource(const ArrayByteSource&) = delete;
+  ArrayByteSource& operator=(const ArrayByteSource&) = delete;
 
   virtual size_t Available() const override;
-  virtual StringPiece Peek() override;
+  virtual absl::string_view Peek() override;
   virtual void Skip(size_t n) override;
 
  private:
-  StringPiece   input_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource);
+  absl::string_view input_;
 };
 
 // Implementation of ByteSource that wraps another ByteSource, limiting the
@@ -330,7 +335,7 @@
   LimitByteSource(ByteSource* source, size_t limit);
 
   virtual size_t Available() const override;
-  virtual StringPiece Peek() override;
+  virtual absl::string_view Peek() override;
   virtual void Skip(size_t n) override;
 
   // We override CopyTo so that we can forward to the underlying source, in
@@ -346,6 +351,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"  // NOLINT
 
 #endif  // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
diff --git a/src/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc
index cb11825..0e5f5a5 100644
--- a/src/google/protobuf/stubs/bytestream_unittest.cc
+++ b/src/google/protobuf/stubs/bytestream_unittest.cc
@@ -28,14 +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/stubs/bytestream.h>
+#include "google/protobuf/stubs/bytestream.h"
 
+#include <gtest/gtest.h>
 #include <stdio.h>
 #include <string.h>
+
 #include <algorithm>
 
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
+#include "google/protobuf/testing/googletest.h"
 
 namespace google {
 namespace protobuf {
@@ -47,22 +48,20 @@
 // one fragment.
 class MockByteSource : public ByteSource {
  public:
-  MockByteSource(StringPiece data, int block_size)
-    : data_(data), block_size_(block_size) {}
+  MockByteSource(absl::string_view 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_);
-  }
+  absl::string_view Peek() { return data_.substr(0, block_size_); }
   void Skip(size_t n) { data_.remove_prefix(n); }
 
  private:
-  StringPiece data_;
+  absl::string_view data_;
   int block_size_;
 };
 
 TEST(ByteSourceTest, CopyTo) {
-  StringPiece data("Hello world!");
+  absl::string_view data("Hello world!");
   MockByteSource source(data, 3);
   std::string str;
   StringByteSink sink(&str);
@@ -72,7 +71,7 @@
 }
 
 TEST(ByteSourceTest, CopySubstringTo) {
-  StringPiece data("Hello world!");
+  absl::string_view data("Hello world!");
   MockByteSource source(data, 3);
   source.Skip(1);
   std::string str;
@@ -84,7 +83,7 @@
 }
 
 TEST(ByteSourceTest, LimitByteSource) {
-  StringPiece data("Hello world!");
+  absl::string_view data("Hello world!");
   MockByteSource source(data, 3);
   LimitByteSource limit_source(&source, 6);
   EXPECT_EQ(6, limit_source.Available());
@@ -110,7 +109,7 @@
 }
 
 TEST(ByteSourceTest, CopyToStringByteSink) {
-  StringPiece data("Hello world!");
+  absl::string_view data("Hello world!");
   MockByteSource source(data, 3);
   std::string str;
   StringByteSink sink(&str);
@@ -123,8 +122,6 @@
  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.
diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h
index 43d546d..691eda4 100644
--- a/src/google/protobuf/stubs/callback.h
+++ b/src/google/protobuf/stubs/callback.h
@@ -3,9 +3,7 @@
 
 #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 +71,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 +572,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..d5c80bc 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/string_view.h"
+#include "google/protobuf/stubs/callback.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/strutil.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_, strings::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 ebb1ca0..bdc03b0 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -43,10 +43,9 @@
 #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"
 
 #ifndef PROTOBUF_USE_EXCEPTIONS
 #if defined(_MSC_VER) && defined(_CPPUNWIND)
@@ -69,7 +68,7 @@
 #include <pthread.h>
 #endif
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace std {}
 
@@ -106,7 +105,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
 
@@ -129,12 +133,12 @@
 // structurally_valid.cc.
 PROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
 
-inline bool IsStructurallyValidUTF8(StringPiece str) {
+inline bool IsStructurallyValidUTF8(absl::string_view 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);
+PROTOBUF_EXPORT int UTF8SpnStructurallyValid(absl::string_view str);
 
 // Coerce UTF-8 byte string in src_str to be
 // a structurally-valid equal-length string by selectively
@@ -148,7 +152,8 @@
 //
 // Optimized for: all structurally valid and no byte copying is done.
 //
-PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(StringPiece str, char* dst,
+PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(absl::string_view str,
+                                                    char* dst,
                                                     char replace_char);
 
 }  // namespace internal
@@ -192,6 +197,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..eb43fd2 100644
--- a/src/google/protobuf/stubs/common_unittest.cc
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -30,17 +30,19 @@
 
 // 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/stubs/strutil.h"
+#include "google/protobuf/testing/googletest.h"
+
 namespace google {
 namespace protobuf {
 namespace {
@@ -56,7 +58,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 +83,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) {
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.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
index e6260d0..cd10c4b 100644
--- a/src/google/protobuf/stubs/stl_util.h
+++ b/src/google/protobuf/stubs/stl_util.h
@@ -33,38 +33,16 @@
 #ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
 #define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
 
-#include <google/protobuf/stubs/common.h>
-
 #include <algorithm>
 
+#include "google/protobuf/stubs/common.h"
+
 // Must be last.
-#include <google/protobuf/port_def.inc>  // NOLINT
+#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.
@@ -85,6 +63,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>  // NOLINT
+#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
index a6ad4c0..2e6613e 100644
--- a/src/google/protobuf/stubs/stringprintf.cc
+++ b/src/google/protobuf/stubs/stringprintf.cc
@@ -30,15 +30,16 @@
 
 // from google3/base/stringprintf.cc
 
-#include <google/protobuf/stubs/stringprintf.h>
+#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 <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>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
 
 namespace google {
 namespace protobuf {
@@ -152,7 +153,7 @@
   for (int i = 0; i < v.size(); ++i) {
     cstr[i] = v[i].c_str();
   }
-  for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) {
+  for (int i = v.size(); i < kStringPrintfVectorMaxArgs; ++i) {
     cstr[i] = &string_printf_empty_block[0];
   }
 
diff --git a/src/google/protobuf/stubs/stringprintf.h b/src/google/protobuf/stubs/stringprintf.h
index e3858be..e1c0561 100644
--- a/src/google/protobuf/stubs/stringprintf.h
+++ b/src/google/protobuf/stubs/stringprintf.h
@@ -41,12 +41,14 @@
 #define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
 
 #include <stdarg.h>
+
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/common.h"
 
-#include <google/protobuf/port_def.inc>
+// Must be last.
+#include "google/protobuf/port_def.inc"  // NOLINT
 
 namespace google {
 namespace protobuf {
@@ -80,6 +82,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index dbecd2b..c53e190 100644
--- a/src/google/protobuf/stubs/stringprintf_unittest.cc
+++ b/src/google/protobuf/stubs/stringprintf_unittest.cc
@@ -30,14 +30,16 @@
 
 // from google3/base/stringprintf_unittest.cc
 
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/stringprintf.h"
+
 #include <gtest/gtest.h>
 
 #include <array>
 #include <cerrno>
 #include <string>
 
+#include "google/protobuf/testing/googletest.h"
+
 namespace google {
 namespace protobuf {
 namespace {
diff --git a/src/google/protobuf/stubs/structurally_valid.cc b/src/google/protobuf/stubs/structurally_valid.cc
index a535736..418b40b 100644
--- a/src/google/protobuf/stubs/structurally_valid.cc
+++ b/src/google/protobuf/stubs/structurally_valid.cc
@@ -30,9 +30,8 @@
 
 // Author: jrm@google.com (Jim Meehan)
 
-#include <google/protobuf/stubs/common.h>
-
-#include <google/protobuf/stubs/stringpiece.h>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/stubs/common.h"
 
 namespace google {
 namespace protobuf {
@@ -563,7 +562,7 @@
   return (bytes_consumed == len);
 }
 
-int UTF8SpnStructurallyValid(StringPiece str) {
+int UTF8SpnStructurallyValid(absl::string_view str) {
   if (!module_initialized_) return str.size();
 
   int bytes_consumed = 0;
@@ -584,7 +583,7 @@
 //
 // Fast case: all is structurally valid and no byte copying is done.
 //
-char* UTF8CoerceToStructurallyValid(StringPiece src_str, char* idst,
+char* UTF8CoerceToStructurallyValid(absl::string_view src_str, char* idst,
                                     const char replace_char) {
   const char* isrc = src_str.data();
   const int len = src_str.length();
@@ -602,7 +601,7 @@
       dst[0] = replace_char;                    // replace one bad byte
       src++;
       dst++;
-      StringPiece str2(src, srclimit - src);
+      absl::string_view str2(src, srclimit - src);
       n = UTF8SpnStructurallyValid(str2);       // scan the remainder
       memmove(dst, src, n);                     // copy next good chunk
       src += n;
diff --git a/src/google/protobuf/stubs/structurally_valid_unittest.cc b/src/google/protobuf/stubs/structurally_valid_unittest.cc
index ebd9c42..bb56a68 100644
--- a/src/google/protobuf/stubs/structurally_valid_unittest.cc
+++ b/src/google/protobuf/stubs/structurally_valid_unittest.cc
@@ -31,9 +31,10 @@
 // Copyright 2008 Google Inc. All Rights Reserved.
 // Author: xpeng@google.com (Peter Peng)
 
-#include <google/protobuf/stubs/common.h>
 #include <gtest/gtest.h>
 
+#include "google/protobuf/stubs/common.h"
+
 namespace google {
 namespace protobuf {
 namespace internal {
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 594c8ea..b6d2049 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -30,18 +30,21 @@
 
 // from google3/strings/strutil.cc
 
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/strutil.h"
 
 #include <errno.h>
-#include <float.h>    // FLT_DIG and DBL_DIG
+#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>
+#include "absl/strings/ascii.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/stl_util.h"
 
 #ifdef _WIN32
 // MSVC has only _snprintf, not snprintf.
@@ -99,7 +102,7 @@
 
   // Strip off leading whitespace.
   int first = 0;
-  while (first < str_length && ascii_isspace(str->at(first))) {
+  while (first < str_length && absl::ascii_isspace(str->at(first))) {
     ++first;
   }
   // If entire string is white space.
@@ -114,7 +117,7 @@
 
   // Strip off trailing whitespace.
   int last = str_length - 1;
-  while (last >= 0 && ascii_isspace(str->at(last))) {
+  while (last >= 0 && absl::ascii_isspace(str->at(last))) {
     --last;
   }
   if (last != (str_length - 1) && last >= 0) {
@@ -176,7 +179,7 @@
 // the characters in the string, not the entire string as a single delimiter.
 // ----------------------------------------------------------------------
 template <typename ITR>
-static inline void SplitStringToIteratorUsing(StringPiece full,
+static inline void SplitStringToIteratorUsing(absl::string_view full,
                                               const char *delim, ITR &result) {
   // Optimize the common case where delim is a single character.
   if (delim[0] != '\0' && delim[1] == '\0') {
@@ -209,7 +212,7 @@
   }
 }
 
-void SplitStringUsing(StringPiece full, const char *delim,
+void SplitStringUsing(absl::string_view full, const char *delim,
                       std::vector<std::string> *result) {
   std::back_insert_iterator<std::vector<std::string> > it(*result);
   SplitStringToIteratorUsing(full, delim, it);
@@ -227,7 +230,7 @@
 // If "pieces" is negative for some reason, it returns the whole string
 // ----------------------------------------------------------------------
 template <typename ITR>
-static inline void SplitStringToIteratorAllowEmpty(StringPiece full,
+static inline void SplitStringToIteratorAllowEmpty(absl::string_view full,
                                                    const char *delim,
                                                    int pieces, ITR &result) {
   std::string::size_type begin_index, end_index;
@@ -246,381 +249,13 @@
   *result++ = std::string(full.substr(begin_index));
 }
 
-void SplitStringAllowEmpty(StringPiece full, const char *delim,
+void SplitStringAllowEmpty(absl::string_view 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
@@ -1289,19 +924,21 @@
 
   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])));
+        static_cast<int>(
+            static_cast<unsigned char>(absl::ascii_tolower(us1[i]))) -
+        static_cast<int>(
+            static_cast<unsigned char>(absl::ascii_tolower(us2[i])));
     if (diff != 0) return diff;
   }
   return 0;
 }
 
-inline bool CaseEqual(StringPiece s1, StringPiece s2) {
+inline bool CaseEqual(absl::string_view s1, absl::string_view s2) {
   if (s1.size() != s2.size()) return false;
   return memcasecmp(s1.data(), s2.data(), s1.size()) == 0;
 }
 
-bool safe_strtob(StringPiece str, bool* value) {
+bool safe_strtob(absl::string_view str, bool *value) {
   GOOGLE_CHECK(value != nullptr) << "nullptr output boolean given.";
   if (CaseEqual(str, "true") || CaseEqual(str, "t") ||
       CaseEqual(str, "yes") || CaseEqual(str, "y") ||
@@ -1333,7 +970,7 @@
   char* endptr;
   *value = internal::NoLocaleStrtod(str, &endptr);
   if (endptr != str) {
-    while (ascii_isspace(*endptr)) ++endptr;
+    while (absl::ascii_isspace(*endptr)) ++endptr;
   }
   // Ignore range errors from strtod.  The values it
   // returns on underflow and overflow are the right
@@ -1395,222 +1032,6 @@
   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);
@@ -1619,11 +1040,11 @@
   std::string tmp;
   int num_replacements = 0;
   int pos = 0;
-  for (StringPiece::size_type match_pos =
+  for (absl::string_view::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())) {
+                                    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);
@@ -1639,6 +1060,7 @@
   return num_replacements;
 }
 
+namespace {
 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.
@@ -1653,7 +1075,6 @@
   // 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;
 
@@ -1686,408 +1107,8 @@
   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,
+int Base64EscapeInternal(const unsigned char *src, int szsrc, char *dest,
+                         int szdest, const absl::string_view base64,
                          bool do_padding) {
   static const char kPad64 = '=';
 
@@ -2186,60 +1207,41 @@
   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);
+                          const absl::string_view 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);
+  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);
+static constexpr absl::string_view kBase64Chars =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static constexpr absl::string_view kWebSafeBase64Chars =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+}  // namespace
+
+namespace strings {
+
+void LegacyBase64EscapeWithoutPadding(absl::string_view src,
+                                      std::string *dest) {
+  Base64EscapeInternal(reinterpret_cast<const unsigned char *>(src.data()),
+                       src.size(), dest, /*do_padding=*/false, kBase64Chars);
 }
 
-void WebSafeBase64Escape(const unsigned char *src, int szsrc, std::string *dest,
-                         bool do_padding) {
-  Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars);
+void WebSafeBase64EscapeWithPadding(absl::string_view src, std::string *dest) {
+  Base64EscapeInternal(reinterpret_cast<const unsigned char *>(src.data()),
+                       src.size(), dest,
+                       /*do_padding=*/true, 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);
-}
+}  // namespace strings
 
 // Helper to append a Unicode code point to a string as UTF8, without bringing
 // in any external dependencies.
@@ -2299,111 +1301,6 @@
   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 {
 
 // ----------------------------------------------------------------------
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index 9658abf..2aa522d 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -33,14 +33,19 @@
 #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>
 
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/stubs/common.h"
+
+// Must be last.
+#include "google/protobuf/port_def.inc"  // NOLINT
+
 namespace google {
 namespace protobuf {
 
@@ -53,49 +58,6 @@
 #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);
@@ -113,7 +75,7 @@
 //    prefix string if the prefix matches, otherwise the original
 //    string.
 // ----------------------------------------------------------------------
-inline bool HasPrefixString(StringPiece str, StringPiece prefix) {
+inline bool HasPrefixString(absl::string_view str, absl::string_view prefix) {
   return str.size() >= prefix.size() &&
          memcmp(str.data(), prefix.data(), prefix.size()) == 0;
 }
@@ -135,7 +97,7 @@
 //    suffix string if the suffix matches, otherwise the original
 //    string.
 // ----------------------------------------------------------------------
-inline bool HasSuffixString(StringPiece str, StringPiece suffix) {
+inline bool HasSuffixString(absl::string_view str, absl::string_view suffix) {
   return str.size() >= suffix.size() &&
          memcmp(str.data() + str.size() - suffix.size(), suffix.data(),
                 suffix.size()) == 0;
@@ -212,140 +174,6 @@
                                           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()
@@ -397,21 +225,21 @@
 // safe_strtof()
 // safe_strtod()
 // ----------------------------------------------------------------------
-PROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value);
+PROTOBUF_EXPORT bool safe_strtob(absl::string_view 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_strto32(absl::string_view str, int32_t* value) {
+  return safe_strto32(std::string(str), 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);
+inline bool safe_strtou32(absl::string_view str, uint32_t* value) {
+  return safe_strtou32(std::string(str), value);
 }
 
 PROTOBUF_EXPORT bool safe_strto64(const std::string& str, int64_t* value);
@@ -419,14 +247,14 @@
 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_strto64(absl::string_view str, int64_t* value) {
+  return safe_strto64(std::string(str), 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);
+inline bool safe_strtou64(absl::string_view str, uint64_t* value) {
+  return safe_strtou64(std::string(str), value);
 }
 
 PROTOBUF_EXPORT bool safe_strtof(const char* str, float* value);
@@ -437,11 +265,11 @@
 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_strtof(absl::string_view str, float* value) {
+  return safe_strtof(std::string(str), value);
 }
-inline bool safe_strtod(StringPiece str, double* value) {
-  return safe_strtod(str.ToString(), value);
+inline bool safe_strtod(absl::string_view str, double* value) {
+  return safe_strtod(std::string(str), value);
 }
 
 // ----------------------------------------------------------------------
@@ -575,216 +403,10 @@
 
 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&);
-};
+using Hex = absl::Hex;
 
 }  // 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.
@@ -802,66 +424,13 @@
                                            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);
+namespace strings {
 // Encode src into dest web-safely with padding.
-PROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src,
+PROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(absl::string_view 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);
+PROTOBUF_EXPORT void LegacyBase64EscapeWithoutPadding(absl::string_view src,
+                                                      std::string* dest);
+}  // namespace strings
 
 inline bool IsValidCodePoint(uint32_t code_point) {
   return code_point < 0xD800 ||
@@ -883,50 +452,8 @@
 // ----------------------------------------------------------------------
 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) {
+inline bool EndsWith(absl::string_view text, absl::string_view suffix) {
   return suffix.empty() ||
       (text.size() >= suffix.size() &&
        memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
@@ -945,6 +472,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 0bb9558..d657579 100644
--- a/src/google/protobuf/stubs/strutil_unittest.cc
+++ b/src/google/protobuf/stubs/strutil_unittest.cc
@@ -30,13 +30,13 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/strutil.h"
 
+#include <gtest/gtest.h>
 #include <locale.h>
 
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
+#include "google/protobuf/stubs/stl_util.h"
+#include "google/protobuf/testing/googletest.h"
 
 #ifdef _WIN32
 #define snprintf _snprintf
@@ -74,755 +74,6 @@
   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>> {};
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 1ce0a1c1..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..b04d8bb 100644
--- a/src/google/protobuf/test_messages_proto2.proto
+++ b/src/google/protobuf/test_messages_proto2.proto
@@ -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..1f51ec8 100644
--- a/src/google/protobuf/test_util2.h
+++ b/src/google/protobuf/test_util2.h
@@ -31,22 +31,29 @@
 #ifndef GOOGLE_PROTOBUF_TEST_UTIL2_H__
 #define GOOGLE_PROTOBUF_TEST_UTIL2_H__
 
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/strutil.h"
 
-#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_replace.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/*
+// Translate net/proto2/* or third_party/protobuf/* to 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());
+  std::string net_proto2 = "net/proto2/";
+  std::string third_party_protobuf = "third_party/protobuf/";
+  std::string path;
+  if (google3_path.find(net_proto2) == 0) {
+    path = google3_path.substr(net_proto2.size());
+  } else {
+    GOOGLE_CHECK(google3_path.find(third_party_protobuf) == 0) << google3_path;
+    path = google3_path.substr(third_party_protobuf.size());
+  }
 
   path = StringReplace(path, "internal/", "", false);
   path = StringReplace(path, "proto/", "", false);
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..350f9a9 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/str_replace.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "google/protobuf/testing/file.h"
 #ifdef _MSC_VER
 // #include <direct.h>
 #else
@@ -150,7 +153,7 @@
   // 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
index 68f8172..facb1ca 100644
--- a/src/google/protobuf/testing/zcgunzip.cc
+++ b/src/google/protobuf/testing/zcgunzip.cc
@@ -53,8 +53,8 @@
 #endif
 #endif
 
-#include <google/protobuf/io/gzip_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#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;
diff --git a/src/google/protobuf/testing/zcgzip.cc b/src/google/protobuf/testing/zcgzip.cc
index 808d058..3ac2cf2 100644
--- a/src/google/protobuf/testing/zcgzip.cc
+++ b/src/google/protobuf/testing/zcgzip.cc
@@ -52,8 +52,8 @@
 #endif
 #endif
 
-#include <google/protobuf/io/gzip_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#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;
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 1911049..cf2afa2 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,35 @@
 #include <climits>
 #include <cmath>
 #include <limits>
+#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 "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 "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/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/stl_util.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -175,14 +181,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 +202,7 @@
     return nullptr;
   }
 
-  return it->second[index].get();
+  return it->second[static_cast<size_t>(index)].get();
 }
 
 namespace {
@@ -294,6 +299,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 +375,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 +434,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.
@@ -507,7 +512,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 +528,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);
         }
 
@@ -695,7 +700,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 +736,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 +850,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 +896,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 +910,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 +964,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);
@@ -981,7 +988,7 @@
   }
 
   // Consumes an identifier and saves its value in the identifier parameter.
-  // Returns false if the token is not of type IDENTFIER.
+  // Returns false if the token is not of type IDENTIFIER.
   bool ConsumeIdentifier(std::string* identifier) {
     if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
       *identifier = tokenizer_.current().text;
@@ -1162,7 +1169,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 +1291,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 +1307,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 +1320,6 @@
     }
 
    private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector);
     TextFormat::Parser::ParserImpl* parser_;
   };
 
@@ -1362,6 +1370,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 +1431,15 @@
   // error.)
   bool failed() const { return failed_; }
 
-  void PrintMaybeWithMarker(StringPiece text) {
+  void PrintMaybeWithMarker(absl::string_view text) {
     Print(text.data(), text.size());
     if (ConsumeInsertSilentMarker()) {
       PrintLiteral(internal::kDebugStringSilentMarker);
     }
   }
 
-  void PrintMaybeWithMarker(StringPiece text_head,
-                            StringPiece text_tail) {
+  void PrintMaybeWithMarker(absl::string_view text_head,
+                            absl::string_view text_tail) {
     Print(text_head.data(), text_head.size());
     if (ConsumeInsertSilentMarker()) {
       PrintLiteral(internal::kDebugStringSilentMarker);
@@ -1438,8 +1448,6 @@
   }
 
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator);
-
   void Write(const char* data, size_t size) {
     if (failed_) return;
     if (size == 0) return;
@@ -1549,7 +1557,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 +1611,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 +1643,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 +1661,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 +1677,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 +1706,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);
 }
@@ -1819,19 +1827,19 @@
 }
 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 {
@@ -1850,7 +1858,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(
@@ -2290,7 +2298,7 @@
 namespace internal {
 class MapFieldPrinterHelper {
  public:
-  // DynamicMapSorter::Sort cannot be used because it enfores syncing with
+  // DynamicMapSorter::Sort cannot be used because it enforces syncing with
   // repeated field.
   static bool SortMap(const Message& message, const Reflection* reflection,
                       const FieldDescriptor* field,
@@ -2510,7 +2518,7 @@
   // 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;
   }
 
@@ -2589,7 +2597,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;
     }
@@ -2639,13 +2647,13 @@
     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->PrintString(absl::StrCat(field.varint()));
         if (single_line_mode_) {
           generator->PrintLiteral(" ");
         } else {
@@ -2656,7 +2664,7 @@
         generator->PrintString(field_number);
         generator->PrintMaybeWithMarker(": ", "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 {
@@ -2668,7 +2676,7 @@
         generator->PrintString(field_number);
         generator->PrintMaybeWithMarker(": ", "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 {
@@ -2708,7 +2716,7 @@
           // 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->PrintString(absl::CEscape(value));
           if (single_line_mode_) {
             generator->PrintLiteral("\" ");
           } else {
@@ -2743,4 +2751,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..bfae7e6 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -44,14 +44,16 @@
 #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"
@@ -76,6 +78,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);
@@ -131,6 +136,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 +174,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 +205,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
@@ -476,13 +480,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 +575,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,8 +674,6 @@
                                     ParseLocationRange location);
   static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree,
                                             const FieldDescriptor* field);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat);
 };
 
 inline void TextFormat::RecordLocation(ParseInfoTree* info_tree,
@@ -688,6 +690,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..e11533d 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,31 +40,35 @@
 #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 "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 <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_replace.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/test_util.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 {
@@ -94,10 +98,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 +119,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,7 +157,7 @@
   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 } "
@@ -229,7 +231,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 +240,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 +256,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 +285,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 +461,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 +485,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 +536,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 +546,7 @@
     if (single_line_mode) {
       return " { ";
     }
-    return StrCat(" {  # ", message.GetDescriptor()->name(), ": ",
+    return absl::StrCat(" {  # ", message.GetDescriptor()->name(), ": ",
                         field_index, "\n");
   }
 };
@@ -590,7 +592,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 +636,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");
   }
 };
 
@@ -817,7 +819,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 +828,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 +847,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 +1037,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 +1084,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 +1116,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 +1176,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 +1414,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 +1455,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 +1649,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
@@ -1904,12 +1917,12 @@
 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 +1936,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 +1945,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 +1961,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 +1969,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 +2290,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..47ecf72 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -47,6 +47,8 @@
   ~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_),
 };
@@ -66,7 +68,7 @@
   "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;
+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,
     "google/protobuf/timestamp.proto",
@@ -304,4 +306,4 @@
 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 6633822..c9fe105 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,19 +19,19 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -159,7 +159,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:
@@ -236,7 +236,7 @@
   return _internal_seconds();
 }
 inline void Timestamp::_internal_set_seconds(int64_t value) {
-  
+
   _impl_.seconds_ = value;
 }
 inline void Timestamp::set_seconds(int64_t value) {
@@ -256,7 +256,7 @@
   return _internal_nanos();
 }
 inline void Timestamp::_internal_set_nanos(int32_t value) {
-  
+
   _impl_.nanos_ = value;
 }
 inline void Timestamp::set_nanos(int32_t value) {
@@ -274,5 +274,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index e29bbb8..760823f 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -119,6 +119,8 @@
   ~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_),
@@ -131,6 +133,8 @@
   ~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_),
@@ -147,6 +151,8 @@
   ~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_),
@@ -158,6 +164,8 @@
   ~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_),
@@ -167,15 +175,17 @@
   ~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)},
+  { 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[] = {
@@ -232,7 +242,7 @@
   &::descriptor_table_google_2fprotobuf_2fany_2eproto,
   &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
 };
-static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2ftype_2eproto_once;
+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,
     "google/protobuf/type.proto",
@@ -521,7 +531,7 @@
       // .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);
+          uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val));
         } else
@@ -885,7 +895,7 @@
       // .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);
+          uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_kind(static_cast<::PROTOBUF_NAMESPACE_ID::Field_Kind>(val));
         } else
@@ -894,7 +904,7 @@
       // .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);
+          uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_cardinality(static_cast<::PROTOBUF_NAMESPACE_ID::Field_Cardinality>(val));
         } else
@@ -1419,7 +1429,7 @@
       // .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);
+          uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val));
         } else
@@ -2154,4 +2164,4 @@
 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 0f11e6c..3491463 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,22 +19,22 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -107,11 +107,15 @@
   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);
+  return Field_Kind_Name(static_cast<Field_Kind>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Field_Kind* value) {
+    ::absl::string_view name, Field_Kind* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Field_Kind>(
     Field_Kind_descriptor(), name, value);
 }
@@ -134,11 +138,15 @@
   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);
+  return Field_Cardinality_Name(static_cast<Field_Cardinality>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Field_Cardinality* value) {
+    ::absl::string_view name, Field_Cardinality* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Field_Cardinality>(
     Field_Cardinality_descriptor(), name, value);
 }
@@ -159,11 +167,15 @@
   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);
+  return Syntax_Name(static_cast<Syntax>(enum_t_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(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Syntax* value) {
+    ::absl::string_view name, Syntax* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Syntax>(
     Syntax_descriptor(), name, value);
 }
@@ -272,7 +284,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:
@@ -522,7 +534,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:
@@ -596,7 +608,7 @@
       "Incorrect type passed to function Kind_Name.");
     return Field_Kind_Name(enum_t_value);
   }
-  static inline bool Kind_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool Kind_Parse(::absl::string_view name,
       Kind* value) {
     return Field_Kind_Parse(name, value);
   }
@@ -630,7 +642,7 @@
       "Incorrect type passed to function Cardinality_Name.");
     return Field_Cardinality_Name(enum_t_value);
   }
-  static inline bool Cardinality_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+  static inline bool Cardinality_Parse(::absl::string_view name,
       Cardinality* value) {
     return Field_Cardinality_Parse(name, value);
   }
@@ -896,7 +908,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:
@@ -1120,7 +1132,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:
@@ -1304,7 +1316,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:
@@ -1407,11 +1419,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() {
@@ -1420,9 +1432,9 @@
 }
 inline void Type::set_allocated_name(std::string* name) {
   if (name != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -1508,8 +1520,7 @@
   // @@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) {
@@ -1529,8 +1540,7 @@
   // @@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) {
@@ -1611,9 +1621,9 @@
   }
   _impl_.source_context_ = source_context;
   if (source_context) {
-    
+
   } else {
-    
+
   }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Type.source_context)
 }
@@ -1665,9 +1675,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)
@@ -1749,7 +1759,7 @@
   return _internal_number();
 }
 inline void Field::_internal_set_number(int32_t value) {
-  
+
   _impl_.number_ = value;
 }
 inline void Field::set_number(int32_t value) {
@@ -1781,11 +1791,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() {
@@ -1794,9 +1804,9 @@
 }
 inline void Field::set_allocated_name(std::string* name) {
   if (name != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -1831,11 +1841,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() {
@@ -1844,9 +1854,9 @@
 }
 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
@@ -1869,7 +1879,7 @@
   return _internal_oneof_index();
 }
 inline void Field::_internal_set_oneof_index(int32_t value) {
-  
+
   _impl_.oneof_index_ = value;
 }
 inline void Field::set_oneof_index(int32_t value) {
@@ -1889,7 +1899,7 @@
   return _internal_packed();
 }
 inline void Field::_internal_set_packed(bool value) {
-  
+
   _impl_.packed_ = value;
 }
 inline void Field::set_packed(bool value) {
@@ -1961,11 +1971,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() {
@@ -1974,9 +1984,9 @@
 }
 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
@@ -2011,11 +2021,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() {
@@ -2024,9 +2034,9 @@
 }
 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
@@ -2065,11 +2075,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() {
@@ -2078,9 +2088,9 @@
 }
 inline void Enum::set_allocated_name(std::string* name) {
   if (name != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -2194,9 +2204,9 @@
   }
   _impl_.source_context_ = source_context;
   if (source_context) {
-    
+
   } else {
-    
+
   }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Enum.source_context)
 }
@@ -2248,9 +2258,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 +2314,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() {
@@ -2317,9 +2327,9 @@
 }
 inline void EnumValue::set_allocated_name(std::string* name) {
   if (name != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -2342,7 +2352,7 @@
   return _internal_number();
 }
 inline void EnumValue::_internal_set_number(int32_t value) {
-  
+
   _impl_.number_ = value;
 }
 inline void EnumValue::set_number(int32_t value) {
@@ -2418,11 +2428,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() {
@@ -2431,9 +2441,9 @@
 }
 inline void Option::set_allocated_name(std::string* name) {
   if (name != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -2467,9 +2477,9 @@
   }
   _impl_.value_ = value;
   if (value) {
-    
+
   } else {
-    
+
   }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Option.value)
 }
@@ -2521,9 +2531,9 @@
       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)
@@ -2567,5 +2577,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto_2epb_2eh
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index f1b0bd0..419a3df 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -221,6 +221,12 @@
   reserved "bar", "baz";
 }
 
+enum TestReservedEnumFields {
+  UNKNOWN = 0;
+  reserved 2, 15, 9 to 11;
+  reserved "bar", "baz";
+}
+
 message TestAllExtensions {
   extensions 1 to max;
 }
@@ -340,6 +346,16 @@
   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;
@@ -459,6 +475,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 {
@@ -1416,3 +1435,131 @@
 }
 
 
+// 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;
+};
+
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/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 74c358e..3a6d8d7 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -32,24 +32,25 @@
 //  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 "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 "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/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 +244,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 +348,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..04b630e 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/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/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..92fff73 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 "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/text_format.h"
+#include "google/protobuf/wire_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/time.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/synchronization/mutex.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/stubs/stl_util.h"
+
 
 namespace google {
 namespace protobuf {
@@ -648,7 +650,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..6b1d3b2
--- /dev/null
+++ b/src/google/protobuf/util/BUILD.bazel
@@ -0,0 +1,307 @@
+################################################################################
+# 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",
+    srcs = ["json_util.cc"],
+    hdrs = ["json_util.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = [
+        ":type_resolver_util",
+        "//src/google/protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/io:zero_copy_sink",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/util/internal:default_value",
+        "//src/google/protobuf/util/internal:json",
+        "//src/google/protobuf/util/internal:protostream",
+        "//src/google/protobuf/util/internal:utility",
+        "@com_google_absl//absl/status",
+    ],
+)
+
+cc_test(
+    name = "json_util_test",
+    srcs = ["json_util_test.cc"],
+    copts = COPTS,
+    data = [
+        "//src/google/protobuf:testdata",
+    ],
+    deps = [
+        ":json_format_cc_proto",
+        ":json_format_proto3_cc_proto",
+        ":json_util",
+        "//src/google/protobuf",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:test_util",
+        "//src/google/protobuf/testing",
+        "//src/google/protobuf/util/internal:maps_cc_proto",
+        "@com_google_absl//absl/status",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+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",
+        "//src/google/protobuf/util/internal:utility",
+        "@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",
+        "//src/google/protobuf/util/internal:test_proto_srcs",
+    ],
+    visibility = [
+        "//pkg:__pkg__",
+        "//python:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "json_format_proto",
+    testonly = 1,
+    srcs = ["json_format.proto"],
+    strip_import_prefix = "/src",
+)
+
+cc_proto_library(
+    name = "json_format_cc_proto",
+    testonly = 1,
+    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,
+    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",
+    ]) + [
+        "//src/google/protobuf/util/internal:test_srcs",
+    ],
+    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..36b51e9 100644
--- a/src/google/protobuf/util/delimited_message_util.cc
+++ b/src/google/protobuf/util/delimited_message_util.cc
@@ -31,8 +31,8 @@
 // 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..9a4e066 100644
--- a/src/google/protobuf/util/delimited_message_util.h
+++ b/src/google/protobuf/util/delimited_message_util.h
@@ -37,12 +37,12 @@
 
 #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 {
@@ -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..954afb2 100644
--- a/src/google/protobuf/util/delimited_message_util_test.cc
+++ b/src/google/protobuf/util/delimited_message_util_test.cc
@@ -31,13 +31,13 @@
 // 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/test_util.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
 
 namespace google {
diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc
index 5d8e865..9161d53 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 {
@@ -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..a6de21c 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/unittest.pb.h"
+#include "google/protobuf/descriptor.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/mathutil.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..a67a025 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 "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/internal/BUILD.bazel b/src/google/protobuf/util/internal/BUILD.bazel
new file mode 100644
index 0000000..a982f16
--- /dev/null
+++ b/src/google/protobuf/util/internal/BUILD.bazel
@@ -0,0 +1,473 @@
+################################################################################
+# Protocol Buffers C++ util internals.
+################################################################################
+
+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")
+
+package(
+    default_visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/util:__pkg__",
+    ],
+)
+
+cc_library(
+    name = "constants",
+    hdrs = ["constants.h"],
+    strip_include_prefix = "/src",
+    deps = [
+        "//src/google/protobuf/stubs",
+    ],
+)
+
+cc_library(
+    name = "datapiece",
+    srcs = ["datapiece.cc"],
+    hdrs = ["datapiece.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":constants",
+        ":utility",
+        "//src/google/protobuf",
+        "//src/google/protobuf/stubs",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "default_value",
+    srcs = ["default_value_objectwriter.cc"],
+    hdrs = ["default_value_objectwriter.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":datapiece",
+        ":object_writer",
+        ":type_info",
+        ":utility",
+        "//src/google/protobuf/stubs",
+    ],
+)
+
+cc_test(
+    name = "default_value_objectwriter_test",
+    srcs = ["default_value_objectwriter_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":default_value",
+        ":default_value_test_cc_proto",
+        ":expecting_objectwriter",
+        ":type_info_test_helper",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "expecting_objectwriter",
+    testonly = 1,
+    hdrs = ["expecting_objectwriter.h"],
+    strip_include_prefix = "/src",
+    deps = [":object_writer"],
+)
+
+cc_library(
+    name = "field_mask_utility",
+    srcs = ["field_mask_utility.cc"],
+    hdrs = ["field_mask_utility.h"],
+    strip_include_prefix = "/src",
+    deps = [
+        ":utility",
+        "//src/google/protobuf/stubs",
+    ],
+)
+
+cc_library(
+    name = "json",
+    srcs = [
+        "json_escaping.cc",
+        "json_objectwriter.cc",
+        "json_stream_parser.cc",
+    ],
+    hdrs = [
+        "json_escaping.h",
+        "json_objectwriter.h",
+        "json_stream_parser.h",
+    ],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":object_writer",
+        ":utility",
+        "//src/google/protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_test(
+    name = "json_objectwriter_test",
+    srcs = ["json_objectwriter_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":json",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "json_stream_parser_test",
+    srcs = ["json_stream_parser_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":expecting_objectwriter",
+        ":json",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "mock_error_listener",
+    testonly = 1,
+    hdrs = ["mock_error_listener.h"],
+    strip_include_prefix = "/src",
+    deps = [":protostream"],
+)
+
+cc_library(
+    name = "object_writer",
+    srcs = ["object_writer.cc"],
+    hdrs = [
+        "object_source.h",
+        "object_writer.h",
+        "structured_objectwriter.h",
+    ],
+    strip_include_prefix = "/src",
+    deps = [
+        ":datapiece",
+        "//src/google/protobuf/stubs",
+    ],
+)
+
+cc_library(
+    name = "type_info",
+    srcs = ["type_info.cc"],
+    hdrs = ["type_info.h"],
+    strip_include_prefix = "/src",
+    deps = [
+        ":utility",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/util:type_resolver_util",
+    ],
+)
+
+cc_library(
+    name = "type_info_test_helper",
+    testonly = 1,
+    srcs = ["type_info_test_helper.cc"],
+    hdrs = ["type_info_test_helper.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":default_value",
+        ":protostream",
+        ":type_info",
+    ],
+)
+
+cc_library(
+    name = "protostream",
+    srcs = [
+        "error_listener.cc",
+        "proto_writer.cc",
+        "protostream_objectsource.cc",
+        "protostream_objectwriter.cc",
+    ],
+    hdrs = [
+        "error_listener.h",
+        "location_tracker.h",
+        "object_location_tracker.h",
+        "proto_writer.h",
+        "protostream_objectsource.h",
+        "protostream_objectwriter.h",
+    ],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":constants",
+        ":datapiece",
+        ":field_mask_utility",
+        ":object_writer",
+        ":type_info",
+        ":utility",
+        "//src/google/protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/util:type_resolver_util",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_test(
+    name = "protostream_objectsource_test",
+    srcs = ["protostream_objectsource_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":anys_cc_proto",
+        ":books_cc_proto",
+        ":expecting_objectwriter",
+        ":field_mask_cc_proto",
+        ":maps_cc_proto",
+        ":oneofs_cc_proto",
+        ":proto3_cc_proto",
+        ":protostream",
+        ":struct_cc_proto",
+        ":timestamp_duration_cc_proto",
+        ":type_info_test_helper",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "protostream_objectwriter_test",
+    srcs = ["protostream_objectwriter_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":anys_cc_proto",
+        ":books_cc_proto",
+        ":field_mask_cc_proto",
+        ":maps_cc_proto",
+        ":mock_error_listener",
+        ":oneofs_cc_proto",
+        ":proto3_cc_proto",
+        ":protostream",
+        ":struct_cc_proto",
+        ":timestamp_duration_cc_proto",
+        ":type_info_test_helper",
+        ":wrappers_cc_proto",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "utility",
+    srcs = ["utility.cc"],
+    hdrs = ["utility.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":constants",
+        "//src/google/protobuf",
+        "//src/google/protobuf/stubs",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+# Testing protos:
+
+proto_library(
+    name = "anys_proto",
+    testonly = 1,
+    srcs = ["testdata/anys.proto"],
+    strip_import_prefix = "/src",
+    deps = [
+        "//:any_proto",
+        "//:duration_proto",
+        "//:empty_proto",
+        "//:struct_proto",
+        "//:timestamp_proto",
+        "//:wrappers_proto",
+    ],
+)
+
+cc_proto_library(
+    name = "anys_cc_proto",
+    testonly = 1,
+    visibility = ["//src/google/protobuf/util:__pkg__"],
+    deps = [":anys_proto"],
+)
+
+proto_library(
+    name = "books_proto",
+    testonly = 1,
+    srcs = ["testdata/books.proto"],
+    strip_import_prefix = "/src",
+    deps = [":anys_proto"],
+)
+
+cc_proto_library(
+    name = "books_cc_proto",
+    testonly = 1,
+    deps = [":books_proto"],
+)
+
+proto_library(
+    name = "default_value_proto",
+    testonly = 1,
+    srcs = ["testdata/default_value.proto"],
+    strip_import_prefix = "/src",
+    deps = [
+        "//:any_proto",
+        "//:struct_proto",
+        "//:wrappers_proto",
+    ],
+)
+
+cc_proto_library(
+    name = "default_value_cc_proto",
+    testonly = 1,
+    deps = [":default_value_proto"],
+)
+
+proto_library(
+    name = "default_value_test_proto",
+    testonly = 1,
+    srcs = ["testdata/default_value_test.proto"],
+    strip_import_prefix = "/src",
+)
+
+cc_proto_library(
+    name = "default_value_test_cc_proto",
+    testonly = 1,
+    deps = [":default_value_test_proto"],
+)
+
+proto_library(
+    name = "field_mask_proto",
+    testonly = 1,
+    srcs = ["testdata/field_mask.proto"],
+    strip_import_prefix = "/src",
+    deps = ["//:field_mask_proto"],
+)
+
+cc_proto_library(
+    name = "field_mask_cc_proto",
+    testonly = 1,
+    deps = [":field_mask_proto"],
+)
+
+proto_library(
+    name = "maps_proto",
+    testonly = 1,
+    srcs = ["testdata/maps.proto"],
+    strip_import_prefix = "/src",
+    deps = ["//:any_proto"],
+)
+
+cc_proto_library(
+    name = "maps_cc_proto",
+    testonly = 1,
+    deps = [":maps_proto"],
+)
+
+proto_library(
+    name = "oneofs_proto",
+    testonly = 1,
+    srcs = ["testdata/oneofs.proto"],
+    strip_import_prefix = "/src",
+    deps = [
+        "//:any_proto",
+        "//:struct_proto",
+        "//:timestamp_proto",
+    ],
+)
+
+cc_proto_library(
+    name = "oneofs_cc_proto",
+    testonly = 1,
+    deps = [":oneofs_proto"],
+)
+
+proto_library(
+    name = "proto3_proto",
+    testonly = 1,
+    srcs = ["testdata/proto3.proto"],
+    strip_import_prefix = "/src",
+)
+
+cc_proto_library(
+    name = "proto3_cc_proto",
+    testonly = 1,
+    deps = [":proto3_proto"],
+)
+
+proto_library(
+    name = "struct_proto",
+    testonly = 1,
+    srcs = ["testdata/struct.proto"],
+    strip_import_prefix = "/src",
+    deps = ["//:struct_proto"],
+)
+
+cc_proto_library(
+    name = "struct_cc_proto",
+    testonly = 1,
+    deps = [":struct_proto"],
+)
+
+proto_library(
+    name = "timestamp_duration_proto",
+    testonly = 1,
+    srcs = ["testdata/timestamp_duration.proto"],
+    strip_import_prefix = "/src",
+    deps = [
+        "//:duration_proto",
+        "//:timestamp_proto",
+    ],
+)
+
+cc_proto_library(
+    name = "timestamp_duration_cc_proto",
+    testonly = 1,
+    deps = [":timestamp_duration_proto"],
+)
+
+proto_library(
+    name = "wrappers_proto",
+    testonly = 1,
+    srcs = ["testdata/wrappers.proto"],
+    strip_import_prefix = "/src",
+    deps = ["//:wrappers_proto"],
+)
+
+cc_proto_library(
+    name = "wrappers_cc_proto",
+    testonly = 1,
+    deps = [":wrappers_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",
+    ]) + [
+        "type_info_test_helper.cc",
+    ],
+)
+
+filegroup(
+    name = "test_proto_srcs",
+    srcs = glob(["testdata/*.proto"]),
+)
diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h
index 8bded86..7c81c47 100644
--- a/src/google/protobuf/util/internal/constants.h
+++ b/src/google/protobuf/util/internal/constants.h
@@ -33,7 +33,7 @@
 
 #include <cstdint>
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/common.h"
 
 // This file contains constants used by //net/proto2/util/converter.
 
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index 3e7aa84..5148329 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -28,36 +28,39 @@
 // (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 "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>
+#include "google/protobuf/struct.pb.h"
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "absl/status/status.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/util/internal/utility.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "google/protobuf/stubs/mathutil.h"
 
 namespace google {
 namespace protobuf {
 namespace util {
 namespace converter {
 
-using util::Status;
+using ::absl::Status;
 
 namespace {
 
 template <typename To, typename From>
-util::StatusOr<To> ValidateNumberConversion(To after, From before) {
+absl::StatusOr<To> ValidateNumberConversion(To after, From before) {
   if (after == before &&
       MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
     return after;
   } else {
-    return util::InvalidArgumentError(
+    return absl::InvalidArgumentError(
         std::is_integral<From>::value       ? ValueAsString(before)
         : std::is_same<From, double>::value ? DoubleAsString(before)
                                             : FloatAsString(before));
@@ -68,7 +71,7 @@
 //     int32, int64, uint32, uint64, double and float
 // except conversion between double and float.
 template <typename To, typename From>
-util::StatusOr<To> NumberConvertAndCheck(From before) {
+absl::StatusOr<To> NumberConvertAndCheck(From before) {
   if (std::is_same<From, To>::value) return before;
 
   To after = static_cast<To>(before);
@@ -78,7 +81,7 @@
 // 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) {
+absl::StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
   if (std::is_same<From, To>::value) return before;
 
   To after = static_cast<To>(before);
@@ -86,13 +89,13 @@
 }
 
 // For conversion between double and float only.
-util::StatusOr<double> FloatToDouble(float before) {
+absl::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) {
+absl::StatusOr<float> DoubleToFloat(double before) {
   if (std::isnan(before)) {
     return std::numeric_limits<float>::quiet_NaN();
   } else if (!std::isfinite(before)) {
@@ -119,7 +122,7 @@
       }
     }
     // Double value outside of the range of float.
-    return util::InvalidArgumentError(DoubleAsString(before));
+    return absl::InvalidArgumentError(DoubleAsString(before));
   } else {
     return static_cast<float>(before);
   }
@@ -127,7 +130,7 @@
 
 }  // namespace
 
-util::StatusOr<int32_t> DataPiece::ToInt32() const {
+absl::StatusOr<int32_t> DataPiece::ToInt32() const {
   if (type_ == TYPE_STRING)
     return StringToNumber<int32_t>(safe_strto32);
 
@@ -140,7 +143,7 @@
   return GenericConvert<int32_t>();
 }
 
-util::StatusOr<uint32_t> DataPiece::ToUint32() const {
+absl::StatusOr<uint32_t> DataPiece::ToUint32() const {
   if (type_ == TYPE_STRING)
     return StringToNumber<uint32_t>(safe_strtou32);
 
@@ -153,7 +156,7 @@
   return GenericConvert<uint32_t>();
 }
 
-util::StatusOr<int64_t> DataPiece::ToInt64() const {
+absl::StatusOr<int64_t> DataPiece::ToInt64() const {
   if (type_ == TYPE_STRING)
     return StringToNumber<int64_t>(safe_strto64);
 
@@ -166,7 +169,7 @@
   return GenericConvert<int64_t>();
 }
 
-util::StatusOr<uint64_t> DataPiece::ToUint64() const {
+absl::StatusOr<uint64_t> DataPiece::ToUint64() const {
   if (type_ == TYPE_STRING)
     return StringToNumber<uint64_t>(safe_strtou64);
 
@@ -179,7 +182,7 @@
   return GenericConvert<uint64_t>();
 }
 
-util::StatusOr<double> DataPiece::ToDouble() const {
+absl::StatusOr<double> DataPiece::ToDouble() const {
   if (type_ == TYPE_FLOAT) {
     return FloatToDouble(float_);
   }
@@ -187,11 +190,11 @@
     if (str_ == "Infinity") return std::numeric_limits<double>::infinity();
     if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity();
     if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN();
-    util::StatusOr<double> value = StringToNumber<double>(safe_strtod);
+    absl::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_, "\""));
+      return absl::InvalidArgumentError(absl::StrCat("\"", str_, "\""));
     } else {
       return value;
     }
@@ -199,7 +202,7 @@
   return GenericConvert<double>();
 }
 
-util::StatusOr<float> DataPiece::ToFloat() const {
+absl::StatusOr<float> DataPiece::ToFloat() const {
   if (type_ == TYPE_DOUBLE) {
     return DoubleToFloat(double_);
   }
@@ -214,44 +217,47 @@
   return GenericConvert<float>();
 }
 
-util::StatusOr<bool> DataPiece::ToBool() const {
+absl::StatusOr<bool> DataPiece::ToBool() const {
   switch (type_) {
     case TYPE_BOOL:
       return bool_;
     case TYPE_STRING:
+      // Calls out to absl::SimpleAtob, which supports "true"/"false",
+      // "yes"/"no", "y"/"n", "t"/"f", and "1"/"0".
       return StringToNumber<bool>(safe_strtob);
     default:
-      return util::InvalidArgumentError(
-          ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
+      break;
   }
+  return absl::InvalidArgumentError(
+      ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
 }
 
-util::StatusOr<std::string> DataPiece::ToString() const {
+absl::StatusOr<std::string> DataPiece::ToString() const {
   switch (type_) {
     case TYPE_STRING:
       return std::string(str_);
     case TYPE_BYTES: {
       std::string base64;
-      Base64Escape(str_, &base64);
+      absl::Base64Escape(str_, &base64);
       return base64;
     }
     default:
-      return util::InvalidArgumentError(
+      return absl::InvalidArgumentError(
           ValueAsStringOrDefault("Cannot convert to string."));
   }
 }
 
 std::string DataPiece::ValueAsStringOrDefault(
-    StringPiece default_string) const {
+    absl::string_view default_string) const {
   switch (type_) {
     case TYPE_INT32:
-      return StrCat(i32_);
+      return absl::StrCat(i32_);
     case TYPE_INT64:
-      return StrCat(i64_);
+      return absl::StrCat(i64_);
     case TYPE_UINT32:
-      return StrCat(u32_);
+      return absl::StrCat(u32_);
     case TYPE_UINT64:
-      return StrCat(u64_);
+      return absl::StrCat(u64_);
     case TYPE_DOUBLE:
       return DoubleAsString(double_);
     case TYPE_FLOAT:
@@ -259,11 +265,11 @@
     case TYPE_BOOL:
       return SimpleBtoa(bool_);
     case TYPE_STRING:
-      return StrCat("\"", str_.ToString(), "\"");
+      return absl::StrCat("\"", str_, "\"");
     case TYPE_BYTES: {
       std::string base64;
-      WebSafeBase64Escape(str_, &base64);
-      return StrCat("\"", base64, "\"");
+      absl::WebSafeBase64Escape(str_, &base64);
+      return absl::StrCat("\"", base64, "\"");
     }
     case TYPE_NULL:
       return "null";
@@ -272,22 +278,22 @@
   }
 }
 
-util::StatusOr<std::string> DataPiece::ToBytes() const {
-  if (type_ == TYPE_BYTES) return str_.ToString();
+absl::StatusOr<std::string> DataPiece::ToBytes() const {
+  if (type_ == TYPE_BYTES) return std::string(str_);
   if (type_ == TYPE_STRING) {
     std::string decoded;
     if (!DecodeBase64(str_, &decoded)) {
-      return util::InvalidArgumentError(
+      return absl::InvalidArgumentError(
           ValueAsStringOrDefault("Invalid data in input."));
     }
     return decoded;
   } else {
-    return util::InvalidArgumentError(ValueAsStringOrDefault(
+    return absl::InvalidArgumentError(ValueAsStringOrDefault(
         "Wrong type. Only String or Bytes can be converted to Bytes."));
   }
 }
 
-util::StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type,
+absl::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,
@@ -302,7 +308,7 @@
     if (value != nullptr) return value->number();
 
     // Check if int version of enum is sent as string.
-    util::StatusOr<int32_t> int_value = ToInt32();
+    absl::StatusOr<int32_t> int_value = ToInt32();
     if (int_value.ok()) {
       if (const google::protobuf::EnumValue* enum_value =
               FindEnumValueByNumberOrNull(enum_type, int_value.value())) {
@@ -316,7 +322,7 @@
     if (should_normalize_enum) {
       for (std::string::iterator it = enum_name.begin(); it != enum_name.end();
            ++it) {
-        *it = *it == '-' ? '_' : ascii_toupper(*it);
+        *it = *it == '-' ? '_' : absl::ascii_toupper(*it);
       }
       value = FindEnumValueByNameOrNull(enum_type, enum_name);
       if (value != nullptr) return value->number();
@@ -342,12 +348,12 @@
     // enum because we preserve unknown enum values as well.
     return ToInt32();
   }
-  return util::InvalidArgumentError(
+  return absl::InvalidArgumentError(
       ValueAsStringOrDefault("Cannot find enum with given value."));
 }
 
 template <typename To>
-util::StatusOr<To> DataPiece::GenericConvert() const {
+absl::StatusOr<To> DataPiece::GenericConvert() const {
   switch (type_) {
     case TYPE_INT32:
       return NumberConvertAndCheck<To, int32_t>(i32_);
@@ -362,35 +368,35 @@
     case TYPE_FLOAT:
       return NumberConvertAndCheck<To, float>(float_);
     default:  // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL
-      return util::InvalidArgumentError(ValueAsStringOrDefault(
+      return absl::InvalidArgumentError(ValueAsStringOrDefault(
           "Wrong type. Bool, Enum, String and Cord not supported in "
           "GenericConvert."));
   }
 }
 
 template <typename To>
-util::StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece,
+absl::StatusOr<To> DataPiece::StringToNumber(bool (*func)(absl::string_view,
                                                           To*)) const {
   if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
-    return util::InvalidArgumentError(StrCat("\"", str_, "\""));
+    return absl::InvalidArgumentError(absl::StrCat("\"", str_, "\""));
   }
   To result;
   if (func(str_, &result)) return result;
-  return util::InvalidArgumentError(
-      StrCat("\"", std::string(str_), "\""));
+  return absl::InvalidArgumentError(
+      absl::StrCat("\"", std::string(str_), "\""));
 }
 
-bool DataPiece::DecodeBase64(StringPiece src, std::string* dest) const {
+bool DataPiece::DecodeBase64(absl::string_view src, std::string* dest) const {
   // Try web-safe decode first, if it fails, try the non-web-safe decode.
-  if (WebSafeBase64Unescape(src, dest)) {
+  if (absl::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);
+      absl::WebSafeBase64Escape(*dest, &encoded);
       // Remove trailing padding '=' characters before comparison.
-      StringPiece src_no_padding = StringPiece(src).substr(
+      absl::string_view src_no_padding = absl::string_view(src).substr(
           0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1
                                       : src.length());
       return encoded == src_no_padding;
@@ -398,12 +404,11 @@
     return true;
   }
 
-  if (Base64Unescape(src, dest)) {
+  if (absl::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(
+      strings::LegacyBase64EscapeWithoutPadding(*dest, &encoded);
+      absl::string_view src_no_padding = absl::string_view(src).substr(
           0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1
                                       : src.length());
       return encoded == src_no_padding;
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
index 6d08349..a69e8f0 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -34,14 +34,15 @@
 #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>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/port.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -54,10 +55,11 @@
 // 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.
+// For string, an absl::string_view is stored. For Cord, a pointer to Cord is
+// stored. Just like absl::string_view, 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.
@@ -93,12 +95,13 @@
       : 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)
+  DataPiece(absl::string_view 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)
+  DataPiece(absl::string_view value, bool /*dummy*/,
+            bool use_strict_base64_decoding)
       : type_(TYPE_BYTES),
         str_(value),
         use_strict_base64_decoding_(use_strict_base64_decoding) {}
@@ -120,41 +123,41 @@
 
   bool use_strict_base64_decoding() { return use_strict_base64_decoding_; }
 
-  StringPiece str() const {
+  absl::string_view 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;
+  absl::StatusOr<int32_t> ToInt32() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a uint32.
-  util::StatusOr<uint32_t> ToUint32() const;
+  absl::StatusOr<uint32_t> ToUint32() const;
 
   // Parses, casts or converts the value stored in the DataPiece into an int64.
-  util::StatusOr<int64_t> ToInt64() const;
+  absl::StatusOr<int64_t> ToInt64() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a uint64.
-  util::StatusOr<uint64_t> ToUint64() const;
+  absl::StatusOr<uint64_t> ToUint64() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a double.
-  util::StatusOr<double> ToDouble() const;
+  absl::StatusOr<double> ToDouble() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a float.
-  util::StatusOr<float> ToFloat() const;
+  absl::StatusOr<float> ToFloat() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a bool.
-  util::StatusOr<bool> ToBool() const;
+  absl::StatusOr<bool> ToBool() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a string.
-  util::StatusOr<std::string> ToString() const;
+  absl::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;
+  std::string ValueAsStringOrDefault(absl::string_view default_string) const;
 
-  util::StatusOr<std::string> ToBytes() const;
+  absl::StatusOr<std::string> ToBytes() const;
 
  private:
   friend class ProtoWriter;
@@ -168,7 +171,7 @@
 
   // 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,
+  absl::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,
@@ -177,15 +180,15 @@
   // For numeric conversion between
   //     int32, int64, uint32, uint64, double, float and bool
   template <typename To>
-  util::StatusOr<To> GenericConvert() const;
+  absl::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;
+  absl::StatusOr<To> StringToNumber(bool (*func)(absl::string_view, To*)) const;
 
   // Decodes a base64 string. Returns true on success.
-  bool DecodeBase64(StringPiece src, std::string* dest) const;
+  bool DecodeBase64(absl::string_view src, std::string* dest) const;
 
   // Helper function to initialize this DataPiece with 'other'.
   void InternalCopy(const DataPiece& other);
@@ -202,7 +205,7 @@
     double double_;
     float float_;
     bool bool_;
-    StringPiece str_;
+    absl::string_view str_;
   };
 
   // Uses a stricter version of base64 decoding for byte fields.
@@ -214,6 +217,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 7f61cda..05eccdf 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.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/util/internal/default_value_objectwriter.h>
+#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>
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/util/internal/constants.h"
+#include "google/protobuf/util/internal/utility.h"
 
 namespace google {
 namespace protobuf {
@@ -47,11 +46,11 @@
 // 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 ConvertTo(absl::string_view value,
+            absl::StatusOr<T> (DataPiece::*converter_fn)() const,
             T default_value) {
   if (value.empty()) return default_value;
-  util::StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
+  absl::StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
   return result.ok() ? result.value() : default_value;
 }
 }  // namespace
@@ -76,7 +75,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(
-    StringPiece name, bool value) {
+    absl::string_view name, bool value) {
   if (current_ == nullptr) {
     ow_->RenderBool(name, value);
   } else {
@@ -86,7 +85,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32(
-    StringPiece name, int32_t value) {
+    absl::string_view name, int32_t value) {
   if (current_ == nullptr) {
     ow_->RenderInt32(name, value);
   } else {
@@ -96,7 +95,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32(
-    StringPiece name, uint32_t value) {
+    absl::string_view name, uint32_t value) {
   if (current_ == nullptr) {
     ow_->RenderUint32(name, value);
   } else {
@@ -106,7 +105,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64(
-    StringPiece name, int64_t value) {
+    absl::string_view name, int64_t value) {
   if (current_ == nullptr) {
     ow_->RenderInt64(name, value);
   } else {
@@ -116,7 +115,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64(
-    StringPiece name, uint64_t value) {
+    absl::string_view name, uint64_t value) {
   if (current_ == nullptr) {
     ow_->RenderUint64(name, value);
   } else {
@@ -126,7 +125,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble(
-    StringPiece name, double value) {
+    absl::string_view name, double value) {
   if (current_ == nullptr) {
     ow_->RenderDouble(name, value);
   } else {
@@ -136,7 +135,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat(
-    StringPiece name, float value) {
+    absl::string_view name, float value) {
   if (current_ == nullptr) {
     ow_->RenderBool(name, value);
   } else {
@@ -146,12 +145,12 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString(
-    StringPiece name, StringPiece value) {
+    absl::string_view name, absl::string_view value) {
   if (current_ == nullptr) {
     ow_->RenderString(name, value);
   } else {
-    // Since StringPiece is essentially a pointer, takes a copy of "value" to
-    // avoid ownership issues.
+    // Since absl::string_view 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));
   }
@@ -159,12 +158,12 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
-    StringPiece name, StringPiece value) {
+    absl::string_view name, absl::string_view value) {
   if (current_ == nullptr) {
     ow_->RenderBytes(name, value);
   } else {
-    // Since StringPiece is essentially a pointer, takes a copy of "value" to
-    // avoid ownership issues.
+    // Since absl::string_view 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));
   }
@@ -172,7 +171,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull(
-    StringPiece name) {
+    absl::string_view name) {
   if (current_ == nullptr) {
     ow_->RenderNull(name);
   } else {
@@ -216,7 +215,7 @@
       field_scrub_callback_(std::move(field_scrub_callback)) {}
 
 DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
-    StringPiece name) {
+    absl::string_view name) {
   if (name.empty() || kind_ != OBJECT) {
     return nullptr;
   }
@@ -283,7 +282,7 @@
       // get the field_type in this case.
       break;
     }
-    util::StatusOr<const google::protobuf::Type*> sub_type =
+    absl::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() << "'.";
@@ -309,11 +308,11 @@
     return;
   }
   std::vector<Node*> new_children;
-  std::unordered_map<std::string, int> orig_children_map;
+  absl::flat_hash_map<absl::string_view, 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);
+    orig_children_map.try_emplace(children_[i]->name_, i);
   }
 
   for (int i = 0; i < type_->fields_size(); ++i) {
@@ -330,8 +329,7 @@
       continue;
     }
 
-    std::unordered_map<std::string, int>::iterator found =
-        orig_children_map.find(field.name());
+    auto 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()) {
@@ -346,7 +344,7 @@
 
     if (field.kind() == google::protobuf::Field::TYPE_MESSAGE) {
       kind = OBJECT;
-      util::StatusOr<const google::protobuf::Type*> found_result =
+      absl::StatusOr<const google::protobuf::Type*> found_result =
           typeinfo->ResolveTypeUrl(field.type_url());
       if (!found_result.ok()) {
         // "field" is of an unknown type.
@@ -498,7 +496,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
-    StringPiece name) {
+    absl::string_view name) {
   if (current_ == nullptr) {
     std::vector<std::string> path;
     root_.reset(CreateNewNode(std::string(name), &type_, OBJECT,
@@ -549,7 +547,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
-    StringPiece name) {
+    absl::string_view name) {
   if (current_ == nullptr) {
     std::vector<std::string> path;
     root_.reset(CreateNewNode(std::string(name), &type_, LIST,
@@ -593,18 +591,18 @@
   return this;
 }
 
-void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
+void DefaultValueObjectWriter::RenderDataPiece(absl::string_view name,
                                                const DataPiece& data) {
   MaybePopulateChildrenOfAny(current_);
   if (current_->type() != nullptr && current_->type()->name() == kAnyType &&
       name == "@type") {
-    util::StatusOr<std::string> data_string = data.ToString();
+    absl::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 =
+      absl::StatusOr<const google::protobuf::Type*> found_type =
           typeinfo_->ResolveTypeUrl(string_value);
       if (!found_type.ok()) {
         GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.";
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index a9e1673..2745159 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -37,16 +37,16 @@
 #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>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.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>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -81,44 +81,46 @@
                            const google::protobuf::Type& type,
                            ObjectWriter* ow);
 
+  DefaultValueObjectWriter(const DefaultValueObjectWriter&) = delete;
+  DefaultValueObjectWriter& operator=(const DefaultValueObjectWriter&) = delete;
   ~DefaultValueObjectWriter() override;
 
   // ObjectWriter methods.
-  DefaultValueObjectWriter* StartObject(StringPiece name) override;
+  DefaultValueObjectWriter* StartObject(absl::string_view name) override;
 
   DefaultValueObjectWriter* EndObject() override;
 
-  DefaultValueObjectWriter* StartList(StringPiece name) override;
+  DefaultValueObjectWriter* StartList(absl::string_view name) override;
 
   DefaultValueObjectWriter* EndList() override;
 
-  DefaultValueObjectWriter* RenderBool(StringPiece name,
+  DefaultValueObjectWriter* RenderBool(absl::string_view name,
                                        bool value) override;
 
-  DefaultValueObjectWriter* RenderInt32(StringPiece name,
+  DefaultValueObjectWriter* RenderInt32(absl::string_view name,
                                         int32_t value) override;
 
-  DefaultValueObjectWriter* RenderUint32(StringPiece name,
+  DefaultValueObjectWriter* RenderUint32(absl::string_view name,
                                          uint32_t value) override;
 
-  DefaultValueObjectWriter* RenderInt64(StringPiece name,
+  DefaultValueObjectWriter* RenderInt64(absl::string_view name,
                                         int64_t value) override;
 
-  DefaultValueObjectWriter* RenderUint64(StringPiece name,
+  DefaultValueObjectWriter* RenderUint64(absl::string_view name,
                                          uint64_t value) override;
 
-  DefaultValueObjectWriter* RenderDouble(StringPiece name,
+  DefaultValueObjectWriter* RenderDouble(absl::string_view name,
                                          double value) override;
 
-  DefaultValueObjectWriter* RenderFloat(StringPiece name,
+  DefaultValueObjectWriter* RenderFloat(absl::string_view name,
                                         float value) override;
 
-  DefaultValueObjectWriter* RenderString(StringPiece name,
-                                         StringPiece value) override;
-  DefaultValueObjectWriter* RenderBytes(StringPiece name,
-                                        StringPiece value) override;
+  DefaultValueObjectWriter* RenderString(absl::string_view name,
+                                         absl::string_view value) override;
+  DefaultValueObjectWriter* RenderBytes(absl::string_view name,
+                                        absl::string_view value) override;
 
-  DefaultValueObjectWriter* RenderNull(StringPiece name) override;
+  DefaultValueObjectWriter* RenderNull(absl::string_view name) override;
 
   // Register the callback for scrubbing of fields.
   void RegisterFieldScrubCallBack(FieldScrubCallBack field_scrub_callback);
@@ -153,6 +155,8 @@
          const std::vector<std::string>& path, bool suppress_empty_list,
          bool preserve_proto_field_names, bool use_ints_for_enums,
          FieldScrubCallBack field_scrub_callback);
+    Node(const Node&) = delete;
+    Node& operator=(const Node&) = delete;
     virtual ~Node() {
       for (int i = 0; i < children_.size(); ++i) {
         delete children_[i];
@@ -163,7 +167,7 @@
     void AddChild(Node* child) { children_.push_back(child); }
 
     // Finds the child given its name.
-    Node* FindChild(StringPiece name);
+    Node* FindChild(absl::string_view 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
@@ -239,9 +243,6 @@
 
     // 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.
@@ -279,7 +280,7 @@
   void WriteRoot();
 
   // Adds or replaces the data_ of a primitive child node.
-  void RenderDataPiece(StringPiece name, const DataPiece& data);
+  void RenderDataPiece(absl::string_view 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
@@ -318,8 +319,6 @@
   FieldScrubCallBack field_scrub_callback_;
 
   ObjectWriter* ow_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter);
 };
 
 }  // namespace converter
@@ -327,6 +326,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 96b14db..a8851b5 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter_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/util/internal/default_value_objectwriter.h>
+#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 "google/protobuf/util/internal/expecting_objectwriter.h"
+#include "google/protobuf/util/internal/constants.h"
+#include "google/protobuf/util/internal/testdata/default_value_test.pb.h"
+#include "google/protobuf/util/internal/type_info_test_helper.h"
 #include <gtest/gtest.h>
 
 namespace google {
diff --git a/src/google/protobuf/util/internal/error_listener.cc b/src/google/protobuf/util/internal/error_listener.cc
index 538307b..a6641fd 100644
--- a/src/google/protobuf/util/internal/error_listener.cc
+++ b/src/google/protobuf/util/internal/error_listener.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/internal/error_listener.h>
+#include "google/protobuf/util/internal/error_listener.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h
index 8c9c501..27fb65c 100644
--- a/src/google/protobuf/util/internal/error_listener.h
+++ b/src/google/protobuf/util/internal/error_listener.h
@@ -36,14 +36,15 @@
 #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>
+#include "google/protobuf/stubs/callback.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/util/internal/location_tracker.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -53,49 +54,46 @@
 // Interface for error listener.
 class PROTOBUF_EXPORT ErrorListener {
  public:
+  ErrorListener(const ErrorListener&) = delete;
+  ErrorListener& operator=(const ErrorListener&) = delete;
   virtual ~ErrorListener() {}
 
   // Reports an invalid name at the given location.
   virtual void InvalidName(const LocationTrackerInterface& loc,
-                           StringPiece invalid_name,
-                           StringPiece message) = 0;
+                           absl::string_view invalid_name,
+                           absl::string_view message) = 0;
 
   // Reports an invalid value for a field.
   virtual void InvalidValue(const LocationTrackerInterface& loc,
-                            StringPiece type_name,
-                            StringPiece value) = 0;
+                            absl::string_view type_name,
+                            absl::string_view value) = 0;
 
   // Reports a missing required field.
   virtual void MissingField(const LocationTrackerInterface& loc,
-                            StringPiece missing_name) = 0;
+                            absl::string_view 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(const NoopErrorListener&) = delete;
+  NoopErrorListener& operator=(const NoopErrorListener&) = delete;
   ~NoopErrorListener() override {}
 
   void InvalidName(const LocationTrackerInterface& /*loc*/,
-                   StringPiece /* invalid_name */,
-                   StringPiece /* message */) override {}
+                   absl::string_view /* invalid_name */,
+                   absl::string_view /* message */) override {}
 
   void InvalidValue(const LocationTrackerInterface& /*loc*/,
-                    StringPiece /* type_name */,
-                    StringPiece /* value */) override {}
+                    absl::string_view /* type_name */,
+                    absl::string_view /* value */) override {}
 
   void MissingField(const LocationTrackerInterface& /* loc */,
-                    StringPiece /* missing_name */) override {}
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener);
+                    absl::string_view /* missing_name */) override {}
 };
 
 
@@ -104,6 +102,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 76fe2b6..8f200d5 100644
--- a/src/google/protobuf/util/internal/expecting_objectwriter.h
+++ b/src/google/protobuf/util/internal/expecting_objectwriter.h
@@ -46,16 +46,16 @@
 //     ->EndObject();
 //
 //   // Actual testing
-//   mock.StartObject(StringPiece())
+//   mock.StartObject(absl::string_view())
 //         ->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>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/util/internal/object_writer.h"
 
 namespace google {
 namespace protobuf {
@@ -74,35 +74,37 @@
  public:
   MockObjectWriter() {}
 
-  MOCK_METHOD(ObjectWriter*, StartObject, (StringPiece), (override));
+  MOCK_METHOD(ObjectWriter*, StartObject, (absl::string_view), (override));
   MOCK_METHOD(ObjectWriter*, EndObject, (), (override));
-  MOCK_METHOD(ObjectWriter*, StartList, (StringPiece), (override));
+  MOCK_METHOD(ObjectWriter*, StartList, (absl::string_view), (override));
   MOCK_METHOD(ObjectWriter*, EndList, (), (override));
-  MOCK_METHOD(ObjectWriter*, RenderBool, (StringPiece, bool), (override));
-  MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32_t),
+  MOCK_METHOD(ObjectWriter*, RenderBool, (absl::string_view, bool), (override));
+  MOCK_METHOD(ObjectWriter*, RenderInt32, (absl::string_view, int32_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32_t),
+  MOCK_METHOD(ObjectWriter*, RenderUint32, (absl::string_view, uint32_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64_t),
+  MOCK_METHOD(ObjectWriter*, RenderInt64, (absl::string_view, int64_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64_t),
+  MOCK_METHOD(ObjectWriter*, RenderUint64, (absl::string_view, uint64_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderDouble, (StringPiece, double),
+  MOCK_METHOD(ObjectWriter*, RenderDouble, (absl::string_view, double),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderFloat, (StringPiece, float),
+  MOCK_METHOD(ObjectWriter*, RenderFloat, (absl::string_view, float),
               (override));
   MOCK_METHOD(ObjectWriter*, RenderString,
-              (StringPiece, StringPiece), (override));
-  MOCK_METHOD(ObjectWriter*, RenderBytes, (StringPiece, StringPiece),
-              (override));
-  MOCK_METHOD(ObjectWriter*, RenderNull, (StringPiece), (override));
+              (absl::string_view, absl::string_view), (override));
+  MOCK_METHOD(ObjectWriter*, RenderBytes,
+              (absl::string_view, absl::string_view), (override));
+  MOCK_METHOD(ObjectWriter*, RenderNull, (absl::string_view), (override));
 };
 
 class ExpectingObjectWriter : public ObjectWriter {
  public:
   explicit ExpectingObjectWriter(MockObjectWriter* mock) : mock_(mock) {}
+  ExpectingObjectWriter(const ExpectingObjectWriter&) = delete;
+  ExpectingObjectWriter& operator=(const ExpectingObjectWriter&) = delete;
 
-  ObjectWriter* StartObject(StringPiece name) override {
+  ObjectWriter* StartObject(absl::string_view name) override {
     (name.empty() ? EXPECT_CALL(*mock_, StartObject(IsEmpty()))
                   : EXPECT_CALL(*mock_, StartObject(Eq(std::string(name)))))
         .WillOnce(Return(mock_))
@@ -117,7 +119,7 @@
     return this;
   }
 
-  ObjectWriter* StartList(StringPiece name) override {
+  ObjectWriter* StartList(absl::string_view name) override {
     (name.empty() ? EXPECT_CALL(*mock_, StartList(IsEmpty()))
                   : EXPECT_CALL(*mock_, StartList(Eq(std::string(name)))))
         .WillOnce(Return(mock_))
@@ -132,7 +134,7 @@
     return this;
   }
 
-  ObjectWriter* RenderBool(StringPiece name, bool value) override {
+  ObjectWriter* RenderBool(absl::string_view name, bool value) override {
     (name.empty()
          ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq<bool>(value)))
          : EXPECT_CALL(*mock_,
@@ -142,7 +144,7 @@
     return this;
   }
 
-  ObjectWriter* RenderInt32(StringPiece name, int32_t value) override {
+  ObjectWriter* RenderInt32(absl::string_view name, int32_t value) override {
     (name.empty()
          ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32_t>(value)))
          : EXPECT_CALL(*mock_, RenderInt32(Eq(std::string(name)),
@@ -152,7 +154,7 @@
     return this;
   }
 
-  ObjectWriter* RenderUint32(StringPiece name, uint32_t value) override {
+  ObjectWriter* RenderUint32(absl::string_view name, uint32_t value) override {
     (name.empty() ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(),
                                                      TypedEq<uint32_t>(value)))
                   : EXPECT_CALL(*mock_, RenderUint32(Eq(std::string(name)),
@@ -162,7 +164,7 @@
     return this;
   }
 
-  ObjectWriter* RenderInt64(StringPiece name, int64_t value) override {
+  ObjectWriter* RenderInt64(absl::string_view name, int64_t value) override {
     (name.empty()
          ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64_t>(value)))
          : EXPECT_CALL(*mock_, RenderInt64(Eq(std::string(name)),
@@ -172,7 +174,7 @@
     return this;
   }
 
-  ObjectWriter* RenderUint64(StringPiece name, uint64_t value) override {
+  ObjectWriter* RenderUint64(absl::string_view name, uint64_t value) override {
     (name.empty() ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(),
                                                      TypedEq<uint64_t>(value)))
                   : EXPECT_CALL(*mock_, RenderUint64(Eq(std::string(name)),
@@ -182,7 +184,7 @@
     return this;
   }
 
-  ObjectWriter* RenderDouble(StringPiece name, double value) override {
+  ObjectWriter* RenderDouble(absl::string_view name, double value) override {
     (name.empty()
          ? EXPECT_CALL(*mock_,
                        RenderDouble(IsEmpty(), NanSensitiveDoubleEq(value)))
@@ -193,7 +195,7 @@
     return this;
   }
 
-  ObjectWriter* RenderFloat(StringPiece name, float value) override {
+  ObjectWriter* RenderFloat(absl::string_view name, float value) override {
     (name.empty()
          ? EXPECT_CALL(*mock_,
                        RenderFloat(IsEmpty(), NanSensitiveFloatEq(value)))
@@ -204,31 +206,32 @@
     return this;
   }
 
-  ObjectWriter* RenderString(StringPiece name,
-                             StringPiece value) override {
+  ObjectWriter* RenderString(absl::string_view name,
+                             absl::string_view value) override {
     (name.empty() ? EXPECT_CALL(*mock_, RenderString(IsEmpty(),
-                                                     TypedEq<StringPiece>(
+                                                     TypedEq<absl::string_view>(
                                                          std::string(value))))
                   : EXPECT_CALL(*mock_, RenderString(Eq(std::string(name)),
-                                                     TypedEq<StringPiece>(
+                                                     TypedEq<absl::string_view>(
                                                          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()))))
+  ObjectWriter* RenderBytes(absl::string_view name,
+                            absl::string_view value) override {
+    (name.empty() ? EXPECT_CALL(*mock_, RenderBytes(IsEmpty(),
+                                                    TypedEq<absl::string_view>(
+                                                        std::string(value))))
+                  : EXPECT_CALL(*mock_, RenderBytes(Eq(std::string(name)),
+                                                    TypedEq<absl::string_view>(
+                                                        std::string(value)))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
   }
 
-  ObjectWriter* RenderNull(StringPiece name) override {
+  ObjectWriter* RenderNull(absl::string_view name) override {
     (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty()))
                   : EXPECT_CALL(*mock_, RenderNull(Eq(std::string(name))))
                         .WillOnce(Return(mock_))
@@ -238,8 +241,6 @@
 
  private:
   MockObjectWriter* mock_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ExpectingObjectWriter);
 };
 
 }  // namespace converter
diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
index 521bf48..e0ffe13 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.cc
+++ b/src/google/protobuf/util/internal/field_mask_utility.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/util/internal/field_mask_utility.h>
+#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>
+#include "absl/status/status.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_cat.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>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -46,8 +47,8 @@
 namespace {
 
 // Appends a FieldMask path segment to a prefix.
-std::string AppendPathSegmentToPrefix(StringPiece prefix,
-                                      StringPiece segment) {
+std::string AppendPathSegmentToPrefix(absl::string_view prefix,
+                                      absl::string_view segment) {
   if (prefix.empty()) {
     return std::string(segment);
   }
@@ -56,14 +57,14 @@
   }
   // If the segment is a map key, appends it to the prefix without the ".".
   if (HasPrefixString(segment, "[\"")) {
-    return StrCat(prefix, segment);
+    return absl::StrCat(prefix, segment);
   }
-  return StrCat(prefix, ".", segment);
+  return absl::StrCat(prefix, ".", segment);
 }
 
 }  // namespace
 
-std::string ConvertFieldMaskPath(const StringPiece path,
+std::string ConvertFieldMaskPath(const absl::string_view path,
                                  ConverterCallback converter) {
   std::string result;
   result.reserve(path.size() << 1);
@@ -107,7 +108,7 @@
   return result;
 }
 
-util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
+absl::Status DecodeCompactFieldMaskPaths(absl::string_view paths,
                                          PathSinkCallback path_sink) {
   std::stack<std::string> prefix;
   int length = paths.length();
@@ -134,7 +135,7 @@
         }
         // Un-escaped '"' must be followed with a ']'.
         if (i >= length - 1 || paths[i + 1] != ']') {
-          return util::InvalidArgumentError(StrCat(
+          return absl::InvalidArgumentError(absl::StrCat(
               "Invalid FieldMask '", paths,
               "'. Map keys should be represented as [\"some_key\"]."));
         }
@@ -145,7 +146,7 @@
         // 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(
+          return absl::InvalidArgumentError(absl::StrCat(
               "Invalid FieldMask '", paths,
               "'. Map keys should be at the end of a path segment."));
         }
@@ -156,7 +157,7 @@
       // 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(
+          return absl::InvalidArgumentError(absl::StrCat(
               "Invalid FieldMask '", paths,
               "'. Map keys should be represented as [\"some_key\"]."));
         }
@@ -173,7 +174,7 @@
     }
     // Gets the current segment - sub-string between previous position (after
     // '(', ')', ',', or the beginning of the input) and the current position.
-    StringPiece segment =
+    absl::string_view segment =
         paths.substr(previous_position, i - previous_position);
     std::string current_prefix = prefix.empty() ? "" : prefix.top();
 
@@ -191,8 +192,8 @@
     // Removes the last prefix after seeing a ')'.
     if (i < length && paths[i] == ')') {
       if (prefix.empty()) {
-        return util::InvalidArgumentError(
-            StrCat("Invalid FieldMask '", paths,
+        return absl::InvalidArgumentError(
+            absl::StrCat("Invalid FieldMask '", paths,
                          "'. Cannot find matching '(' for all ')'."));
       }
       prefix.pop();
@@ -200,16 +201,16 @@
     previous_position = i + 1;
   }
   if (in_map_key) {
-    return util::InvalidArgumentError(
-        StrCat("Invalid FieldMask '", paths,
+    return absl::InvalidArgumentError(
+        absl::StrCat("Invalid FieldMask '", paths,
                      "'. Cannot find matching ']' for all '['."));
   }
   if (!prefix.empty()) {
-    return util::InvalidArgumentError(
-        StrCat("Invalid FieldMask '", paths,
+    return absl::InvalidArgumentError(
+        absl::StrCat("Invalid FieldMask '", paths,
                      "'. Cannot find matching ')' for all '('."));
   }
-  return util::Status();
+  return absl::Status();
 }
 
 }  // namespace converter
diff --git a/src/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h
index 1882333..0db911a 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.h
+++ b/src/google/protobuf/util/internal/field_mask_utility.h
@@ -36,25 +36,25 @@
 #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>
+#include "google/protobuf/stubs/callback.h"
+#include "absl/status/status.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.h"
+
 
 namespace google {
 namespace protobuf {
 namespace util {
 namespace converter {
 
-typedef std::function<std::string(StringPiece)> ConverterCallback;
-typedef std::function<util::Status(StringPiece)> PathSinkCallback;
+typedef std::function<std::string(absl::string_view)> ConverterCallback;
+typedef std::function<absl::Status(absl::string_view)> 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,
+std::string ConvertFieldMaskPath(const absl::string_view path,
                                  ConverterCallback converter);
 
 // Decodes a compact list of FieldMasks. For example, "a.b,a.c.d,a.c.e" will be
@@ -63,7 +63,7 @@
 // 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,
+absl::Status DecodeCompactFieldMaskPaths(absl::string_view paths,
                                          PathSinkCallback path_sink);
 
 }  // namespace converter
diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
index e4fa8cf..3cda954 100644
--- a/src/google/protobuf/util/internal/json_escaping.cc
+++ b/src/google/protobuf/util/internal/json_escaping.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/util/internal/json_escaping.h>
+#include "google/protobuf/util/internal/json_escaping.h"
 
 #include <cstdint>
 
-#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 {
@@ -127,7 +127,7 @@
 // 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,
+bool ReadCodePoint(absl::string_view 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.
@@ -190,9 +190,9 @@
 }
 
 // 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) {
+// and returns an absl::string_view that points to this buffer. The input
+// buffer needs to be at least 6 bytes long.
+absl::string_view ToHex(uint16_t cp, char* buffer) {
   buffer[5] = kHex[cp & 0x0f];
   cp >>= 4;
   buffer[4] = kHex[cp & 0x0f];
@@ -200,13 +200,13 @@
   buffer[3] = kHex[cp & 0x0f];
   cp >>= 4;
   buffer[2] = kHex[cp & 0x0f];
-  return StringPiece(buffer, 6);
+  return absl::string_view(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) {
+// and returns an absl::string_view that points to this buffer. The input
+// buffer needs to be at least 12 bytes long.
+absl::string_view ToSurrogateHex(uint32_t cp, char* buffer) {
   uint16_t low = ToLowSurrogate(cp);
   uint16_t high = ToHighSurrogate(cp);
 
@@ -226,17 +226,17 @@
   high >>= 4;
   buffer[2] = kHex[high & 0x0f];
 
-  return StringPiece(buffer, 12);
+  return absl::string_view(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 needs escaping, then returns the escaped
+// form. The returned absl::string_view 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 the given unicode code point does not need escaping, an empty string is
+// returned.
+absl::string_view EscapeCodePoint(uint32_t cp, char* buffer) {
   if (cp < 0xa0) return kCommonEscapes[cp];
   switch (cp) {
     // These are not required by json spec
@@ -268,33 +268,33 @@
         return ToSurrogateHex(cp, buffer);
       }
   }
-  return StringPiece();
+  return absl::string_view();
 }
 
 // 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,
+absl::string_view EscapeCodePoint(uint32_t cp, char* buffer,
                                   bool force_output) {
-  StringPiece sp = EscapeCodePoint(cp, buffer);
+  absl::string_view 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);
+      sp = absl::string_view(buffer + 4, 2);
       return sp;
     }
     buffer[4] = (cp & 0x3f) | 0x80;
     cp >>= 6;
     if (cp <= 0x0f) {
       buffer[3] = cp | 0xe0;
-      sp = StringPiece(buffer + 3, 3);
+      sp = absl::string_view(buffer + 3, 3);
       return sp;
     }
     buffer[3] = (cp & 0x3f) | 0x80;
     buffer[2] = ((cp >> 6) & 0x07) | 0xf0;
-    sp = StringPiece(buffer + 2, 4);
+    sp = absl::string_view(buffer + 2, 4);
   }
   return sp;
 }
@@ -307,8 +307,8 @@
   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;
+    absl::string_view str = input->Peek();
+    absl::string_view escaped;
     int i = 0;
     int num_read;
     bool ok;
@@ -317,7 +317,7 @@
     //   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.
+    //  iv) end of the string is reached.
     do {
       ok = ReadCodePoint(str, i, &cp, &num_left, &num_read);
       if (num_left > 0 || !ok) break;  // case iii or iv
@@ -344,7 +344,7 @@
   }
 }
 
-void JsonEscaping::Escape(StringPiece input, strings::ByteSink* output) {
+void JsonEscaping::Escape(absl::string_view input, strings::ByteSink* output) {
   const size_t len = input.length();
   const char* p = input.data();
 
diff --git a/src/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h
index 7d54f22..98b0e5b 100644
--- a/src/google/protobuf/util/internal/json_escaping.h
+++ b/src/google/protobuf/util/internal/json_escaping.h
@@ -33,8 +33,9 @@
 
 #include <cstdint>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/bytestream.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/bytestream.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -76,6 +77,8 @@
   static constexpr uint32_t kMaxCodePoint = 0x10ffff;
 
   JsonEscaping() {}
+  JsonEscaping(const JsonEscaping&) = delete;
+  JsonEscaping& operator=(const JsonEscaping&) = delete;
   virtual ~JsonEscaping() {}
 
   // Escape the given ByteSource to the given ByteSink.
@@ -84,10 +87,7 @@
   // 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);
+  static void Escape(absl::string_view input, strings::ByteSink* output);
 };
 
 }  // namespace converter
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
index 1a86f00..ad9f5a1 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -28,32 +28,34 @@
 // (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 "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>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/base/casts.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/util/internal/json_escaping.h"
+#include "google/protobuf/util/internal/utility.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) {
+JsonObjectWriter* JsonObjectWriter::StartObject(absl::string_view name) {
   WritePrefix(name);
   WriteChar('{');
   PushObject();
@@ -67,7 +69,7 @@
   return this;
 }
 
-JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) {
+JsonObjectWriter* JsonObjectWriter::StartList(absl::string_view name) {
   WritePrefix(name);
   WriteChar('[');
   PushArray();
@@ -81,40 +83,40 @@
   return this;
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name,
+JsonObjectWriter* JsonObjectWriter::RenderBool(absl::string_view name,
                                                bool value) {
   return RenderSimple(name, value ? "true" : "false");
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name,
+JsonObjectWriter* JsonObjectWriter::RenderInt32(absl::string_view name,
                                                 int32_t value) {
-  return RenderSimple(name, StrCat(value));
+  return RenderSimple(name, absl::StrCat(value));
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name,
+JsonObjectWriter* JsonObjectWriter::RenderUint32(absl::string_view name,
                                                  uint32_t value) {
-  return RenderSimple(name, StrCat(value));
+  return RenderSimple(name, absl::StrCat(value));
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name,
+JsonObjectWriter* JsonObjectWriter::RenderInt64(absl::string_view name,
                                                 int64_t value) {
   WritePrefix(name);
   WriteChar('"');
-  WriteRawString(StrCat(value));
+  WriteRawString(absl::StrCat(value));
   WriteChar('"');
   return this;
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
+JsonObjectWriter* JsonObjectWriter::RenderUint64(absl::string_view name,
                                                  uint64_t value) {
   WritePrefix(name);
   WriteChar('"');
-  WriteRawString(StrCat(value));
+  WriteRawString(absl::StrCat(value));
   WriteChar('"');
   return this;
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
+JsonObjectWriter* JsonObjectWriter::RenderDouble(absl::string_view name,
                                                  double value) {
   if (std::isfinite(value)) {
     return RenderSimple(name, SimpleDtoa(value));
@@ -124,7 +126,7 @@
   return RenderString(name, DoubleAsString(value));
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name,
+JsonObjectWriter* JsonObjectWriter::RenderFloat(absl::string_view name,
                                                 float value) {
   if (std::isfinite(value)) {
     return RenderSimple(name, SimpleFtoa(value));
@@ -134,8 +136,8 @@
   return RenderString(name, FloatAsString(value));
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name,
-                                                 StringPiece value) {
+JsonObjectWriter* JsonObjectWriter::RenderString(absl::string_view name,
+                                                 absl::string_view value) {
   WritePrefix(name);
   WriteChar('"');
   JsonEscaping::Escape(value, &sink_);
@@ -143,15 +145,15 @@
   return this;
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name,
-                                                StringPiece value) {
+JsonObjectWriter* JsonObjectWriter::RenderBytes(absl::string_view name,
+                                                absl::string_view value) {
   WritePrefix(name);
   std::string base64;
 
   if (use_websafe_base64_for_bytes_)
-    WebSafeBase64EscapeWithPadding(std::string(value), &base64);
+    strings::WebSafeBase64EscapeWithPadding(value, &base64);
   else
-    Base64Escape(value, &base64);
+    absl::Base64Escape(value, &base64);
 
   WriteChar('"');
   // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes
@@ -162,15 +164,15 @@
   return this;
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) {
+JsonObjectWriter* JsonObjectWriter::RenderNull(absl::string_view name) {
   return RenderSimple(name, "null");
 }
 
-JsonObjectWriter* JsonObjectWriter::RenderNullAsEmpty(StringPiece name) {
+JsonObjectWriter* JsonObjectWriter::RenderNullAsEmpty(absl::string_view name) {
   return RenderSimple(name, "");
 }
 
-void JsonObjectWriter::WritePrefix(StringPiece name) {
+void JsonObjectWriter::WritePrefix(absl::string_view name) {
   bool not_first = !element()->is_first();
   if (not_first) WriteChar(',');
   if (not_first || !element()->is_root()) NewLine();
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
index cb7dff6..443cdb4 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.h
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
@@ -35,12 +35,12 @@
 #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>
+#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>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
@@ -90,7 +90,7 @@
 // JsonObjectWriter is thread-unsafe.
 class PROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter {
  public:
-  JsonObjectWriter(StringPiece indent_string, io::CodedOutputStream* out)
+  JsonObjectWriter(absl::string_view indent_string, io::CodedOutputStream* out)
       : element_(new Element(/*parent=*/nullptr, /*is_json_object=*/false)),
         stream_(out),
         sink_(out),
@@ -111,27 +111,30 @@
       }
     }
   }
+  JsonObjectWriter(const JsonObjectWriter&) = delete;
+  JsonObjectWriter& operator=(const JsonObjectWriter&) = delete;
   ~JsonObjectWriter() override;
 
   // ObjectWriter methods.
-  JsonObjectWriter* StartObject(StringPiece name) override;
+  JsonObjectWriter* StartObject(absl::string_view name) override;
   JsonObjectWriter* EndObject() override;
-  JsonObjectWriter* StartList(StringPiece name) override;
+  JsonObjectWriter* StartList(absl::string_view name) override;
   JsonObjectWriter* EndList() override;
-  JsonObjectWriter* RenderBool(StringPiece name, bool value) override;
-  JsonObjectWriter* RenderInt32(StringPiece name, int32_t value) override;
-  JsonObjectWriter* RenderUint32(StringPiece name,
+  JsonObjectWriter* RenderBool(absl::string_view name, bool value) override;
+  JsonObjectWriter* RenderInt32(absl::string_view name, int32_t value) override;
+  JsonObjectWriter* RenderUint32(absl::string_view name,
                                  uint32_t value) override;
-  JsonObjectWriter* RenderInt64(StringPiece name, int64_t value) override;
-  JsonObjectWriter* RenderUint64(StringPiece name,
+  JsonObjectWriter* RenderInt64(absl::string_view name, int64_t value) override;
+  JsonObjectWriter* RenderUint64(absl::string_view 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);
+  JsonObjectWriter* RenderDouble(absl::string_view name, double value) override;
+  JsonObjectWriter* RenderFloat(absl::string_view name, float value) override;
+  JsonObjectWriter* RenderString(absl::string_view name,
+                                 absl::string_view value) override;
+  JsonObjectWriter* RenderBytes(absl::string_view name,
+                                absl::string_view value) override;
+  JsonObjectWriter* RenderNull(absl::string_view name) override;
+  virtual JsonObjectWriter* RenderNullAsEmpty(absl::string_view name);
 
   void set_use_websafe_base64_for_bytes(bool value) {
     use_websafe_base64_for_bytes_ = value;
@@ -144,6 +147,8 @@
         : BaseElement(parent),
           is_first_(true),
           is_json_object_(is_json_object) {}
+    Element(const Element&) = delete;
+    Element& operator=(const Element&) = delete;
 
     // Called before each field of the Element is to be processed.
     // Returns true if this is the first call (processing the first field).
@@ -162,8 +167,6 @@
    private:
     bool is_first_;
     bool is_json_object_;
-
-    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Element);
   };
 
   Element* element() override { return element_.get(); }
@@ -172,6 +175,8 @@
   class PROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink {
    public:
     explicit ByteSinkWrapper(io::CodedOutputStream* stream) : stream_(stream) {}
+    ByteSinkWrapper(const ByteSinkWrapper&) = delete;
+    ByteSinkWrapper& operator=(const ByteSinkWrapper&) = delete;
     ~ByteSinkWrapper() override {}
 
     // ByteSink methods.
@@ -181,15 +186,13 @@
 
    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) {
+  JsonObjectWriter* RenderSimple(absl::string_view name,
+                                 absl::string_view value) {
     WritePrefix(name);
     WriteRawString(value);
     return this;
@@ -242,13 +245,13 @@
   // 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);
+  void WritePrefix(absl::string_view 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) {
+  void WriteRawString(absl::string_view s) {
     stream_->WriteRaw(s.data(), s.length());
   }
 
@@ -264,8 +267,6 @@
   // 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
@@ -273,6 +274,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 8acf2c5..33b24de 100644
--- a/src/google/protobuf/util/internal/json_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter_test.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/util/internal/json_objectwriter.h>
+#include "google/protobuf/util/internal/json_objectwriter.h"
 
 #include <cstdint>
 
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/util/internal/utility.h>
+#include "google/protobuf/util/internal/utility.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index 5c34dbc..eccedb9 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.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/internal/json_stream_parser.h>
+#include "google/protobuf/util/internal/json_stream_parser.h"
 
 #include <algorithm>
 #include <cctype>
@@ -37,12 +37,16 @@
 #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>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/strutil.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/string_view.h"
+#include "google/protobuf/util/internal/object_writer.h"
+#include "google/protobuf/util/internal/json_escaping.h"
 
 
 namespace google {
@@ -57,9 +61,9 @@
 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";
+static const absl::string_view kKeywordTrue = "true";
+static const absl::string_view kKeywordFalse = "false";
+static const absl::string_view kKeywordNull = "null";
 
 inline bool IsLetter(char c) {
   return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') ||
@@ -72,31 +76,31 @@
 
 // Indicates a character may not be part of an unquoted key.
 inline bool IsKeySeparator(char c) {
-  return (ascii_isspace(c) || c == '"' || c == '\'' || c == '{' ||
+  return (absl::ascii_isspace(c) || c == '"' || c == '\'' || c == '{' ||
           c == '}' || c == '[' || c == ']' || c == ':' || c == ',');
 }
 
-inline void ReplaceInvalidCodePoints(StringPiece str,
+inline void ReplaceInvalidCodePoints(absl::string_view 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);
+    absl::string_view valid_part = str.substr(0, n_valid_bytes);
+    absl::StrAppend(dst, valid_part);
 
     if (n_valid_bytes == str.size()) {
       break;
     }
 
     // Append replacement value.
-    StrAppend(dst, replacement);
+    absl::StrAppend(dst, replacement);
 
     // Move past valid bytes + one invalid byte.
     str.remove_prefix(n_valid_bytes + 1);
   }
 }
 
-static bool ConsumeKey(StringPiece* input, StringPiece* key) {
+static bool ConsumeKey(absl::string_view* input, absl::string_view* key) {
   if (input->empty() || !IsLetter((*input)[0])) return false;
   int len = 1;
   for (; len < input->size(); ++len) {
@@ -104,14 +108,14 @@
       break;
     }
   }
-  *key = StringPiece(input->data(), len);
-  *input = StringPiece(input->data() + len, input->size() - len);
+  *key = absl::string_view(input->data(), len);
+  *input = absl::string_view(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) {
+static bool ConsumeKeyPermissive(absl::string_view* input,
+                                 absl::string_view* key) {
   if (input->empty() || !IsLetter((*input)[0])) return false;
   int len = 1;
   for (; len < input->size(); ++len) {
@@ -119,12 +123,12 @@
       break;
     }
   }
-  *key = StringPiece(input->data(), len);
-  *input = StringPiece(input->data() + len, input->size() - len);
+  *key = absl::string_view(input->data(), len);
+  *input = absl::string_view(input->data() + len, input->size() - len);
   return true;
 }
 
-static bool MatchKey(StringPiece input) {
+static bool MatchKey(absl::string_view input) {
   return !input.empty() && IsLetter(input[0]);
 }
 
@@ -157,40 +161,40 @@
 JsonStreamParser::~JsonStreamParser() {}
 
 
-util::Status JsonStreamParser::Parse(StringPiece json) {
-  StringPiece chunk = json;
+absl::Status JsonStreamParser::Parse(absl::string_view json) {
+  absl::string_view 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
+  // and create a new absl::string_view 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_);
+    absl::StrAppend(&chunk_storage_, json);
+    chunk = absl::string_view(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));
+    absl::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));
+    absl::StrAppend(&leftover_, chunk.substr(n));
     return status;
   } else {
     leftover_.assign(chunk.data(), chunk.size());
-    return util::Status();
+    return absl::Status();
   }
 }
 
-util::Status JsonStreamParser::FinishParse() {
+absl::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();
+    return absl::Status();
   }
 
   // Lifetime needs to last until RunParser returns, so keep this variable
@@ -215,7 +219,7 @@
   // 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();
+  absl::Status result = RunParser();
   if (result.ok()) {
     SkipWhitespace();
     if (!p_.empty()) {
@@ -227,14 +231,14 @@
   return result;
 }
 
-util::Status JsonStreamParser::ParseChunk(StringPiece chunk) {
+absl::Status JsonStreamParser::ParseChunk(absl::string_view chunk) {
   // Do not do any work if the chunk is empty.
-  if (chunk.empty()) return util::Status();
+  if (chunk.empty()) return absl::Status();
 
   p_ = json_ = chunk;
 
   finishing_ = false;
-  util::Status result = RunParser();
+  absl::Status result = RunParser();
   if (!result.ok()) return result;
 
   SkipWhitespace();
@@ -253,7 +257,7 @@
     // unparsed data left, we save it for later parse.
     leftover_ = std::string(p_);
   }
-  return util::Status();
+  return absl::Status();
 }
 
 bool JsonStreamParser::IsInputAllWhiteSpaces(TokenType type) {
@@ -267,16 +271,16 @@
   return false;
 }
 
-util::Status JsonStreamParser::RunParser() {
+absl::Status JsonStreamParser::RunParser() {
   while (!stack_.empty()) {
     ParseType type = stack_.top();
     TokenType t = (string_open_ == 0) ? GetNextTokenType() : BEGIN_STRING;
     stack_.pop();
-    util::Status result;
+    absl::Status result;
     switch (type) {
       case VALUE:
         if (allow_no_root_element_ && IsInputAllWhiteSpaces(t)) {
-          return util::Status();
+          return absl::Status();
         }
         result = ParseValue(t);
         break;
@@ -303,28 +307,28 @@
 
       default:
         result =
-            util::InternalError(StrCat("Unknown parse type: ", type));
+            absl::InternalError(absl::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)) {
+      if (!finishing_ && absl::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_);
+          absl::StrAppend(&key_storage_, key_);
+          key_ = absl::string_view(key_storage_);
         }
-        result = util::Status();
+        result = absl::Status();
       }
       return result;
     }
   }
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status JsonStreamParser::ParseValue(TokenType type) {
+absl::Status JsonStreamParser::ParseValue(TokenType type) {
   switch (type) {
     case BEGIN_OBJECT:
       return HandleBeginObject();
@@ -348,7 +352,7 @@
       // 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("");
+        return absl::CancelledError("");
       }
 
       if (allow_empty_null_ && IsEmptyNullAllowed(type)) {
@@ -360,18 +364,18 @@
   }
 }
 
-util::Status JsonStreamParser::ParseString() {
-  util::Status result = ParseStringHelper();
+absl::Status JsonStreamParser::ParseString() {
+  absl::Status result = ParseStringHelper();
   if (result.ok()) {
     ow_->RenderString(key_, parsed_);
-    key_ = StringPiece();
-    parsed_ = StringPiece();
+    key_ = absl::string_view();
+    parsed_ = absl::string_view();
     parsed_storage_.clear();
   }
   return result;
 }
 
-util::Status JsonStreamParser::ParseStringHelper() {
+absl::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();
@@ -391,14 +395,14 @@
       // depending on if we expect more data later.
       if (p_.length() == 1) {
         if (!finishing_) {
-          return util::CancelledError("");
+          return absl::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();
+        absl::Status result = ParseUnicodeEscape();
         if (!result.ok()) {
           return result;
         }
@@ -438,18 +442,18 @@
     if (*data == string_open_) {
       // If we didn't copy anything, reuse the input buffer.
       if (parsed_storage_.empty()) {
-        parsed_ = StringPiece(last, data - last);
+        parsed_ = absl::string_view(last, data - last);
       } else {
         if (last < data) {
           parsed_storage_.append(last, data - last);
         }
-        parsed_ = StringPiece(parsed_storage_);
+        parsed_ = absl::string_view(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();
+      return absl::Status();
     }
     // Normal character, just advance past it.
     Advance();
@@ -460,7 +464,7 @@
   }
   // If we didn't find the closing quote but we expect more data, cancel for now
   if (!finishing_) {
-    return util::CancelledError("");
+    return absl::CancelledError("");
   }
   // End of string reached without a closing quote, report an error.
   string_open_ = 0;
@@ -475,10 +479,10 @@
 // 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() {
+absl::Status JsonStreamParser::ParseUnicodeEscape() {
   if (p_.length() < kUnicodeEscapedLength) {
     if (!finishing_) {
-      return util::CancelledError("");
+      return absl::CancelledError("");
     }
     return ReportFailure("Illegal hex string.",
                          ParseErrorType::ILLEGAL_HEX_STRING);
@@ -497,7 +501,7 @@
       code <= JsonEscaping::kMaxHighSurrogate) {
     if (p_.length() < 2 * kUnicodeEscapedLength) {
       if (!finishing_) {
-        return util::CancelledError("");
+        return absl::CancelledError("");
       }
       if (!coerce_to_utf8_) {
         return ReportFailure("Missing low surrogate.",
@@ -539,27 +543,27 @@
   // Advance past the [final] code unit escape.
   p_.remove_prefix(kUnicodeEscapedLength);
   parsed_storage_.append(buf, len);
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status JsonStreamParser::ParseNumber() {
+absl::Status JsonStreamParser::ParseNumber() {
   NumberResult number;
-  util::Status result = ParseNumberHelper(&number);
+  absl::Status result = ParseNumberHelper(&number);
   if (result.ok()) {
     switch (number.type) {
       case NumberResult::DOUBLE:
         ow_->RenderDouble(key_, number.double_val);
-        key_ = StringPiece();
+        key_ = absl::string_view();
         break;
 
       case NumberResult::INT:
         ow_->RenderInt64(key_, number.int_val);
-        key_ = StringPiece();
+        key_ = absl::string_view();
         break;
 
       case NumberResult::UINT:
         ow_->RenderUint64(key_, number.uint_val);
-        key_ = StringPiece();
+        key_ = absl::string_view();
         break;
 
       default:
@@ -570,7 +574,7 @@
   return result;
 }
 
-util::Status JsonStreamParser::ParseDoubleHelper(const std::string& number,
+absl::Status JsonStreamParser::ParseDoubleHelper(const std::string& number,
                                                  NumberResult* result) {
   if (!safe_strtod(number, &result->double_val)) {
     return ReportFailure("Unable to parse number.",
@@ -581,10 +585,10 @@
                          ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
   }
   result->type = NumberResult::DOUBLE;
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
+absl::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
   const char* data = p_.data();
   int length = p_.length();
 
@@ -611,7 +615,7 @@
   // If the entire input is a valid number, and we may have more content in the
   // future, we abort for now and resume when we know more.
   if (index == length && !finishing_) {
-    return util::CancelledError("");
+    return absl::CancelledError("");
   }
 
   // Create a string containing just the number, so we can use safe_strtoX
@@ -619,7 +623,7 @@
 
   // Floating point number, parse as a double.
   if (floating) {
-    util::Status status = ParseDoubleHelper(number, result);
+    absl::Status status = ParseDoubleHelper(number, result);
     if (status.ok()) {
       p_.remove_prefix(index);
     }
@@ -637,10 +641,10 @@
     if (safe_strtou64(number, &result->uint_val)) {
       result->type = NumberResult::UINT;
       p_.remove_prefix(index);
-      return util::Status();
+      return absl::Status();
     } else {
       // If the value is too large, parse it as double.
-      util::Status status = ParseDoubleHelper(number, result);
+      absl::Status status = ParseDoubleHelper(number, result);
       if (status.ok()) {
         p_.remove_prefix(index);
       }
@@ -658,10 +662,10 @@
   if (safe_strto64(number, &result->int_val)) {
     result->type = NumberResult::INT;
     p_.remove_prefix(index);
-    return util::Status();
+    return absl::Status();
   } else {
     // If the value is too large, parse it as double.
-    util::Status status = ParseDoubleHelper(number, result);
+    absl::Status status = ParseDoubleHelper(number, result);
     if (status.ok()) {
       p_.remove_prefix(index);
     }
@@ -669,7 +673,7 @@
   }
 }
 
-util::Status JsonStreamParser::HandleBeginObject() {
+absl::Status JsonStreamParser::HandleBeginObject() {
   GOOGLE_DCHECK_EQ('{', *p_.data());
   Advance();
   ow_->StartObject(key_);
@@ -677,12 +681,12 @@
   if (!status.ok()) {
     return status;
   }
-  key_ = StringPiece();
+  key_ = absl::string_view();
   stack_.push(ENTRY);
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status JsonStreamParser::ParseObjectMid(TokenType type) {
+absl::Status JsonStreamParser::ParseObjectMid(TokenType type) {
   if (type == UNKNOWN) {
     return ReportUnknown("Expected , or } after key:value pair.",
                          ParseErrorType::EXPECTED_COMMA_OR_BRACES);
@@ -693,20 +697,20 @@
     Advance();
     ow_->EndObject();
     --recursion_depth_;
-    return util::Status();
+    return absl::Status();
   }
   // Found a comma, advance past it and get ready for an entry.
   if (type == VALUE_SEPARATOR) {
     Advance();
     stack_.push(ENTRY);
-    return util::Status();
+    return absl::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) {
+absl::Status JsonStreamParser::ParseEntry(TokenType type) {
   if (type == UNKNOWN) {
     return ReportUnknown("Expected an object key or }.",
                          ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
@@ -717,10 +721,10 @@
     ow_->EndObject();
     Advance();
     --recursion_depth_;
-    return util::Status();
+    return absl::Status();
   }
 
-  util::Status result;
+  absl::Status result;
   if (type == BEGIN_STRING) {
     // Key is a string (standard JSON), parse it and store the string.
     result = ParseStringHelper();
@@ -728,14 +732,15 @@
       key_storage_.clear();
       if (!parsed_storage_.empty()) {
         parsed_storage_.swap(key_storage_);
-        key_ = StringPiece(key_storage_);
+        key_ = absl::string_view(key_storage_);
       } else {
         key_ = parsed_;
       }
-      parsed_ = StringPiece();
+      parsed_ = absl::string_view();
     }
   } else if (type == BEGIN_KEY) {
-    // Key is a bare key (back compat), create a StringPiece pointing to it.
+    // Key is a bare key (back compat), create a absl::string_view 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.
@@ -758,7 +763,7 @@
   return result;
 }
 
-util::Status JsonStreamParser::ParseEntryMid(TokenType type) {
+absl::Status JsonStreamParser::ParseEntryMid(TokenType type) {
   if (type == UNKNOWN) {
     return ReportUnknown("Expected : between key:value pair.",
                          ParseErrorType::EXPECTED_COLON);
@@ -766,22 +771,22 @@
   if (type == ENTRY_SEPARATOR) {
     Advance();
     stack_.push(VALUE);
-    return util::Status();
+    return absl::Status();
   }
   return ReportFailure("Expected : between key:value pair.",
                        ParseErrorType::EXPECTED_COLON);
 }
 
-util::Status JsonStreamParser::HandleBeginArray() {
+absl::Status JsonStreamParser::HandleBeginArray() {
   GOOGLE_DCHECK_EQ('[', *p_.data());
   Advance();
   ow_->StartList(key_);
-  key_ = StringPiece();
+  key_ = absl::string_view();
   stack_.push(ARRAY_VALUE);
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status JsonStreamParser::ParseArrayValue(TokenType type) {
+absl::Status JsonStreamParser::ParseArrayValue(TokenType type) {
   if (type == UNKNOWN) {
     return ReportUnknown("Expected a value or ] within an array.",
                          ParseErrorType::EXPECTED_VALUE_OR_BRACKET);
@@ -790,15 +795,15 @@
   if (type == END_ARRAY) {
     ow_->EndList();
     Advance();
-    return util::Status();
+    return absl::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)) {
+  absl::Status result = ParseValue(type);
+  if (absl::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();
@@ -806,7 +811,7 @@
   return result;
 }
 
-util::Status JsonStreamParser::ParseArrayMid(TokenType type) {
+absl::Status JsonStreamParser::ParseArrayMid(TokenType type) {
   if (type == UNKNOWN) {
     return ReportUnknown("Expected , or ] after array value.",
                          ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
@@ -815,45 +820,45 @@
   if (type == END_ARRAY) {
     ow_->EndList();
     Advance();
-    return util::Status();
+    return absl::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();
+    return absl::Status();
   }
   // Illegal token after array value.
   return ReportFailure("Expected , or ] after array value.",
                        ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
 }
 
-util::Status JsonStreamParser::ParseTrue() {
+absl::Status JsonStreamParser::ParseTrue() {
   ow_->RenderBool(key_, true);
-  key_ = StringPiece();
+  key_ = absl::string_view();
   p_.remove_prefix(kKeywordTrue.length());
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status JsonStreamParser::ParseFalse() {
+absl::Status JsonStreamParser::ParseFalse() {
   ow_->RenderBool(key_, false);
-  key_ = StringPiece();
+  key_ = absl::string_view();
   p_.remove_prefix(kKeywordFalse.length());
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status JsonStreamParser::ParseNull() {
+absl::Status JsonStreamParser::ParseNull() {
   ow_->RenderNull(key_);
-  key_ = StringPiece();
+  key_ = absl::string_view();
   p_.remove_prefix(kKeywordNull.length());
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status JsonStreamParser::ParseEmptyNull() {
+absl::Status JsonStreamParser::ParseEmptyNull() {
   ow_->RenderNull(key_);
-  key_ = StringPiece();
-  return util::Status();
+  key_ = absl::string_view();
+  return absl::Status();
 }
 
 bool JsonStreamParser::IsEmptyNullAllowed(TokenType type) {
@@ -862,7 +867,7 @@
          stack_.top() == OBJ_MID;
 }
 
-util::Status JsonStreamParser::ReportFailure(StringPiece message,
+absl::Status JsonStreamParser::ReportFailure(absl::string_view message,
                                              ParseErrorType parse_code) {
   (void)parse_code;  // Parameter is used in Google-internal code.
   static const int kContextLength = 20;
@@ -871,54 +876,54 @@
   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);
+  absl::string_view segment(begin, end - begin);
   std::string location(p_start - begin, ' ');
   location.push_back('^');
-  auto status = util::InvalidArgumentError(
-      StrCat(message, "\n", segment, "\n", location));
+  auto status = absl::InvalidArgumentError(
+      absl::StrCat(message, "\n", segment, "\n", location));
   return status;
 }
 
-util::Status JsonStreamParser::ReportUnknown(StringPiece message,
+absl::Status JsonStreamParser::ReportUnknown(absl::string_view message,
                                              ParseErrorType parse_code) {
   // If we aren't finishing the parse, cancel parsing and try later.
   if (!finishing_) {
-    return util::CancelledError("");
+    return absl::CancelledError("");
   }
   if (p_.empty()) {
-    return ReportFailure(StrCat("Unexpected end of string. ", message),
+    return ReportFailure(absl::StrCat("Unexpected end of string. ", message),
                          parse_code);
   }
   return ReportFailure(message, parse_code);
 }
 
-util::Status JsonStreamParser::IncrementRecursionDepth(
-    StringPiece key) const {
+absl::Status JsonStreamParser::IncrementRecursionDepth(
+    absl::string_view key) const {
   if (++recursion_depth_ > max_recursion_depth_) {
-    return util::InvalidArgumentError(StrCat(
+    return absl::InvalidArgumentError(absl::StrCat(
         "Message too deep. Max recursion depth reached for key '", key, "'"));
   }
-  return util::Status();
+  return absl::Status();
 }
 
 void JsonStreamParser::SkipWhitespace() {
-  while (!p_.empty() && ascii_isspace(*p_.data())) {
+  while (!p_.empty() && absl::ascii_isspace(*p_.data())) {
     Advance();
   }
-  if (!p_.empty() && !ascii_isspace(*p_.data())) {
+  if (!p_.empty() && !absl::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.
+  // the length of the string.
   p_.remove_prefix(std::min<int>(
       p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
 }
 
-util::Status JsonStreamParser::ParseKey() {
-  StringPiece original = p_;
+absl::Status JsonStreamParser::ParseKey() {
+  absl::string_view original = p_;
 
   if (allow_permissive_key_naming_) {
     if (!ConsumeKeyPermissive(&p_, &key_)) {
@@ -936,11 +941,11 @@
   // we can't know if the key was complete or not.
   if (!finishing_ && p_.empty()) {
     p_ = original;
-    return util::CancelledError("");
+    return absl::CancelledError("");
   }
   // Since we aren't using the key storage, clear it out.
   key_storage_.clear();
-  return util::Status();
+  return absl::Status();
 }
 
 JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() {
@@ -955,7 +960,7 @@
   // 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);
+  absl::string_view data_view = absl::string_view(data, size);
   if (*data == '\"' || *data == '\'') return BEGIN_STRING;
   if (*data == '-' || ('0' <= *data && *data <= '9')) {
     return BEGIN_NUMBER;
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
index 09f17ad..9f30a05 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -35,13 +35,14 @@
 #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>
+#include "google/protobuf/stubs/common.h"
+#include "absl/status/status.h"
+#include "google/protobuf/port.h"
+#include "absl/strings/string_view.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -75,20 +76,23 @@
  public:
   // Creates a JsonStreamParser that will write to the given ObjectWriter.
   explicit JsonStreamParser(ObjectWriter* ow);
+  JsonStreamParser() = delete;
+  JsonStreamParser(const JsonStreamParser&) = delete;
+  JsonStreamParser& operator=(const JsonStreamParser&) = delete;
   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);
+  // Parses a UTF-8 encoded JSON string from an absl::string_view. 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.
+  absl::Status Parse(absl::string_view 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();
+  absl::Status FinishParse();
 
 
   // Sets the max recursion depth of JSON message to be deserialized. JSON
@@ -164,69 +168,69 @@
   };
 
   // Parses a single chunk of JSON, returning an error if the JSON was invalid.
-  util::Status ParseChunk(StringPiece chunk);
+  absl::Status ParseChunk(absl::string_view 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();
+  absl::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);
+  absl::Status ParseValue(TokenType type);
 
   // Parses a string and writes it out to the ow_.
-  util::Status ParseString();
+  absl::Status ParseString();
 
   // Parses a string, storing the result in parsed_.
-  util::Status ParseStringHelper();
+  absl::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();
+  absl::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();
+  absl::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);
+  absl::Status ParseNumberHelper(NumberResult* result);
 
   // Parse a number as double into a NumberResult.
-  util::Status ParseDoubleHelper(const std::string& number,
+  absl::Status ParseDoubleHelper(const std::string& number,
                                  NumberResult* result);
 
   // Handles a { during parsing of a value.
-  util::Status HandleBeginObject();
+  absl::Status HandleBeginObject();
 
   // Parses from the ENTRY state.
-  util::Status ParseEntry(TokenType type);
+  absl::Status ParseEntry(TokenType type);
 
   // Parses from the ENTRY_MID state.
-  util::Status ParseEntryMid(TokenType type);
+  absl::Status ParseEntryMid(TokenType type);
 
   // Parses from the OBJ_MID state.
-  util::Status ParseObjectMid(TokenType type);
+  absl::Status ParseObjectMid(TokenType type);
 
   // Handles a [ during parsing of a value.
-  util::Status HandleBeginArray();
+  absl::Status HandleBeginArray();
 
   // Parses from the ARRAY_VALUE state.
-  util::Status ParseArrayValue(TokenType type);
+  absl::Status ParseArrayValue(TokenType type);
 
   // Parses from the ARRAY_MID state.
-  util::Status ParseArrayMid(TokenType type);
+  absl::Status ParseArrayMid(TokenType type);
 
   // Expects p_ to point to an unquoted literal
-  util::Status ParseTrue();
-  util::Status ParseFalse();
-  util::Status ParseNull();
-  util::Status ParseEmptyNull();
+  absl::Status ParseTrue();
+  absl::Status ParseFalse();
+  absl::Status ParseNull();
+  absl::Status ParseEmptyNull();
 
   // Whether an empty-null is allowed in the current state.
   bool IsEmptyNullAllowed(TokenType type);
@@ -235,19 +239,19 @@
   bool IsInputAllWhiteSpaces(TokenType type);
 
   // Report a failure as a util::Status.
-  util::Status ReportFailure(StringPiece message,
+  absl::Status ReportFailure(absl::string_view 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,
+  absl::Status ReportUnknown(absl::string_view 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;
+  absl::Status IncrementRecursionDepth(absl::string_view key) const;
 
   // Advance p_ past all whitespace or until the end of the string.
   void SkipWhitespace();
@@ -256,7 +260,7 @@
   void Advance();
 
   // Expects p_ to point to the beginning of a key.
-  util::Status ParseKey();
+  absl::Status ParseKey();
 
   // Return the type of the next token at p_.
   TokenType GetNextTokenType();
@@ -274,13 +278,13 @@
 
   // The current chunk of JSON being parsed. Primarily used for providing
   // context during error reporting.
-  StringPiece json_;
+  absl::string_view json_;
 
   // A pointer within the current JSON being parsed, used to track location.
-  StringPiece p_;
+  absl::string_view p_;
 
   // Stores the last key read, as we separate parsing of keys and values.
-  StringPiece key_;
+  absl::string_view key_;
 
   // Storage for key_ if we need to keep ownership, for example between chunks
   // or if the key was unescaped from a JSON string.
@@ -301,7 +305,7 @@
   bool allow_no_root_element_;
 
   // String we parsed during a call to ParseStringHelper().
-  StringPiece parsed_;
+  absl::string_view parsed_;
 
   // Storage for the string we parsed. This may be empty if the string was able
   // to be parsed directly from the input.
@@ -336,8 +340,6 @@
 
   // Maximum allowed recursion depth.
   int max_recursion_depth_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser);
 };
 
 }  // namespace converter
@@ -345,6 +347,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 40157a2..9d3fd4c 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -28,17 +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/json_stream_parser.h>
+#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 "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>
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+#include "absl/time/time.h"
+#include "google/protobuf/util/internal/object_writer.h"
 
 
 namespace google {
@@ -87,7 +88,7 @@
   JsonStreamParserTest() : mock_(), ow_(&mock_) {}
   ~JsonStreamParserTest() override {}
 
-  util::Status RunTest(StringPiece json, int split,
+  absl::Status RunTest(absl::string_view json, int split,
                        std::function<void(JsonStreamParser*)> setup) {
     JsonStreamParser parser(&mock_);
     setup(&parser);
@@ -96,8 +97,8 @@
     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);
+        absl::string_view single = json.substr(i, 1);
+        absl::Status result = parser.Parse(single);
         if (!result.ok()) {
           return result;
         }
@@ -106,10 +107,10 @@
     }
 
     // Normal case, split at the split point and parse two substrings.
-    StringPiece first = json.substr(0, split);
-    StringPiece rest = json.substr(split);
+    absl::string_view first = json.substr(0, split);
+    absl::string_view rest = json.substr(split);
     GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest;
-    util::Status result = parser.Parse(first);
+    absl::Status result = parser.Parse(first);
     if (result.ok()) {
       result = parser.Parse(rest);
       if (result.ok()) {
@@ -123,10 +124,10 @@
   }
 
   void DoTest(
-      StringPiece json, int split,
+      absl::string_view json, int split,
       std::function<void(JsonStreamParser*)> setup = [](JsonStreamParser* p) {
       }) {
-    util::Status result = RunTest(json, split, setup);
+    absl::Status result = RunTest(json, split, setup);
     if (!result.ok()) {
       GOOGLE_LOG(WARNING) << result;
     }
@@ -134,23 +135,23 @@
   }
 
   void DoErrorTest(
-      StringPiece json, int split, StringPiece error_prefix,
+      absl::string_view json, int split, absl::string_view 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());
+    absl::Status result = RunTest(json, split, setup);
+    EXPECT_TRUE(absl::IsInvalidArgument(result));
+    absl::string_view error_message(result.message());
     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
   }
 
   void DoErrorTest(
-      StringPiece json, int split, StringPiece error_prefix,
+      absl::string_view json, int split, absl::string_view 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());
+    absl::Status result = RunTest(json, split, setup);
+    EXPECT_TRUE(absl::IsInvalidArgument(result));
+    absl::string_view error_message(result.message());
     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
   }
 
@@ -170,7 +171,7 @@
 
 // - true, false, null
 TEST_F(JsonStreamParserTest, SimpleTrue) {
-  StringPiece str = "true";
+  absl::string_view str = "true";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderBool("", true);
     DoTest(str, i);
@@ -178,7 +179,7 @@
 }
 
 TEST_F(JsonStreamParserTest, SimpleFalse) {
-  StringPiece str = "false";
+  absl::string_view str = "false";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderBool("", false);
     DoTest(str, i);
@@ -186,7 +187,7 @@
 }
 
 TEST_F(JsonStreamParserTest, SimpleNull) {
-  StringPiece str = "null";
+  absl::string_view str = "null";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderNull("");
     DoTest(str, i);
@@ -195,7 +196,7 @@
 
 // - empty object and array.
 TEST_F(JsonStreamParserTest, EmptyObject) {
-  StringPiece str = "{}";
+  absl::string_view str = "{}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->EndObject();
     DoTest(str, i);
@@ -203,7 +204,7 @@
 }
 
 TEST_F(JsonStreamParserTest, EmptyList) {
-  StringPiece str = "[]";
+  absl::string_view str = "[]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->EndList();
     DoTest(str, i);
@@ -212,7 +213,7 @@
 
 // - negative and positive double and int, unsigned int
 TEST_F(JsonStreamParserTest, SimpleDouble) {
-  StringPiece str = "42.5";
+  absl::string_view str = "42.5";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderDouble("", 42.5);
     DoTest(str, i);
@@ -220,7 +221,7 @@
 }
 
 TEST_F(JsonStreamParserTest, ScientificDouble) {
-  StringPiece str = "1.2345e-10";
+  absl::string_view str = "1.2345e-10";
   for (int i = 0; i < str.length(); ++i) {
     ow_.RenderDouble("", 1.2345e-10);
     DoTest(str, i);
@@ -228,7 +229,7 @@
 }
 
 TEST_F(JsonStreamParserTest, SimpleNegativeDouble) {
-  StringPiece str = "-1045.235";
+  absl::string_view str = "-1045.235";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderDouble("", -1045.235);
     DoTest(str, i);
@@ -236,7 +237,7 @@
 }
 
 TEST_F(JsonStreamParserTest, SimpleInt) {
-  StringPiece str = "123456";
+  absl::string_view str = "123456";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderUint64("", 123456);
     DoTest(str, i);
@@ -244,7 +245,7 @@
 }
 
 TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
-  StringPiece str = "-79497823553162765";
+  absl::string_view str = "-79497823553162765";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderInt64("", int64_t{-79497823553162765});
     DoTest(str, i);
@@ -252,7 +253,7 @@
 }
 
 TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
-  StringPiece str = "11779497823553162765";
+  absl::string_view str = "11779497823553162765";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderUint64("", uint64_t{11779497823553162765u});
     DoTest(str, i);
@@ -260,7 +261,7 @@
 }
 
 TEST_F(JsonStreamParserTest, OctalNumberIsInvalid) {
-  StringPiece str = "01234";
+  absl::string_view 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);
@@ -273,7 +274,7 @@
 }
 
 TEST_F(JsonStreamParserTest, HexNumberIsInvalid) {
-  StringPiece str = "0x1234";
+  absl::string_view 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);
@@ -292,7 +293,7 @@
 
 // - single and double quoted strings
 TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) {
-  StringPiece str = "\"\"";
+  absl::string_view str = "\"\"";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderString("", "");
     DoTest(str, i);
@@ -300,7 +301,7 @@
 }
 
 TEST_F(JsonStreamParserTest, EmptySingleQuotedString) {
-  StringPiece str = "''";
+  absl::string_view str = "''";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderString("", "");
     DoTest(str, i);
@@ -308,7 +309,7 @@
 }
 
 TEST_F(JsonStreamParserTest, SimpleDoubleQuotedString) {
-  StringPiece str = "\"Some String\"";
+  absl::string_view str = "\"Some String\"";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderString("", "Some String");
     DoTest(str, i);
@@ -316,7 +317,7 @@
 }
 
 TEST_F(JsonStreamParserTest, SimpleSingleQuotedString) {
-  StringPiece str = "'Another String'";
+  absl::string_view str = "'Another String'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderString("", "Another String");
     DoTest(str, i);
@@ -325,7 +326,7 @@
 
 // - string key, unquoted key, numeric key
 TEST_F(JsonStreamParserTest, ObjectKeyTypes) {
-  StringPiece str =
+  absl::string_view str =
       "{'s': true, \"d\": false, key: null, snake_key: [], camelKey: {}}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")
@@ -342,7 +343,7 @@
 }
 
 TEST_F(JsonStreamParserTest, UnquotedObjectKeyWithReservedPrefxes) {
-  StringPiece str = "{ nullkey: \"a\", truekey: \"b\", falsekey: \"c\"}";
+  absl::string_view str = "{ nullkey: \"a\", truekey: \"b\", falsekey: \"c\"}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")
         ->RenderString("nullkey", "a")
@@ -354,7 +355,7 @@
 }
 
 TEST_F(JsonStreamParserTest, UnquotedObjectKeyWithReservedKeyword) {
-  StringPiece str = "{ null: \"a\", true: \"b\", false: \"c\"}";
+  absl::string_view 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);
@@ -362,7 +363,7 @@
 }
 
 TEST_F(JsonStreamParserTest, UnquotedObjectKeyWithEmbeddedNonAlphanumeric) {
-  StringPiece str = "{ foo-bar-baz: \"a\"}";
+  absl::string_view str = "{ foo-bar-baz: \"a\"}";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Expected : between key:value pair.",
                 ParseErrorType::EXPECTED_COLON);
@@ -372,7 +373,7 @@
 
 // - array containing primitive values (true, false, null, num, string)
 TEST_F(JsonStreamParserTest, ArrayPrimitiveValues) {
-  StringPiece str = "[true, false, null, 'one', \"two\"]";
+  absl::string_view str = "[true, false, null, 'one', \"two\"]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")
         ->RenderBool("", true)
@@ -387,7 +388,7 @@
 
 // - array containing array, object
 TEST_F(JsonStreamParserTest, ArrayComplexValues) {
-  StringPiece str =
+  absl::string_view str =
       "[[22, -127, 45.3, -1056.4, 11779497823553162765], {'key': true}]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")
@@ -409,7 +410,7 @@
 
 // - object containing array, object, value (true, false, null, num, string)
 TEST_F(JsonStreamParserTest, ObjectValues) {
-  StringPiece str =
+  absl::string_view 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}}";
@@ -439,7 +440,7 @@
 
 
 TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) {
-  StringPiece json = "{\"address\":\xFF\"חרושת 23, רעננה, ישראל\"}";
+  absl::string_view 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);
@@ -455,7 +456,7 @@
 
 // - unicode handling in strings
 TEST_F(JsonStreamParserTest, UnicodeEscaping) {
-  StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
+  absl::string_view str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")
         ->RenderString("", "\xD8\xB9\xD8\xB1\xD8\xA8\xD9\x89")
@@ -466,7 +467,7 @@
 
 // - unicode UTF-16 surrogate pair handling in strings
 TEST_F(JsonStreamParserTest, UnicodeSurrogatePairEscaping) {
-  StringPiece str =
+  absl::string_view str =
       "[\"\\u0bee\\ud800\\uddf1\\uD80C\\uDDA4\\uD83d\\udC1D\\uD83C\\uDF6F\"]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")
@@ -481,7 +482,7 @@
 
 TEST_F(JsonStreamParserTest, UnicodeEscapingInvalidCodePointWhenNotCoerced) {
   // A low surrogate alone.
-  StringPiece str = "[\"\\ude36\"]";
+  absl::string_view str = "[\"\\ude36\"]";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Invalid unicode code point.",
                 ParseErrorType::INVALID_UNICODE);
@@ -490,7 +491,7 @@
 
 TEST_F(JsonStreamParserTest, UnicodeEscapingMissingLowSurrogateWhenNotCoerced) {
   // A high surrogate alone.
-  StringPiece str = "[\"\\ud83d\"]";
+  absl::string_view str = "[\"\\ud83d\"]";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Missing low surrogate.",
                 ParseErrorType::MISSING_LOW_SURROGATE);
@@ -517,7 +518,7 @@
 
 // - ascii escaping (\b, \f, \n, \r, \t, \v)
 TEST_F(JsonStreamParserTest, AsciiEscaping) {
-  StringPiece str =
+  absl::string_view str =
       "[\"\\b\", \"\\ning\", \"test\\f\", \"\\r\\t\", \"test\\\\\\ving\"]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")
@@ -533,7 +534,7 @@
 
 // - trailing commas, we support a single trailing comma but no internal commas.
 TEST_F(JsonStreamParserTest, TrailingCommas) {
-  StringPiece str = "[['a',true,], {b: null,},]";
+  absl::string_view str = "[['a',true,], {b: null,},]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")
         ->StartList("")
@@ -552,7 +553,7 @@
 
 // illegal literals
 TEST_F(JsonStreamParserTest, ExtraTextAfterTrue) {
-  StringPiece str = "truee";
+  absl::string_view str = "truee";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderBool("", true);
     DoErrorTest(str, i, "Parsing terminated before end of input.",
@@ -561,7 +562,7 @@
 }
 
 TEST_F(JsonStreamParserTest, InvalidNumberDashOnly) {
-  StringPiece str = "-";
+  absl::string_view str = "-";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Unable to parse number.",
                 ParseErrorType::UNABLE_TO_PARSE_NUMBER);
@@ -569,7 +570,7 @@
 }
 
 TEST_F(JsonStreamParserTest, InvalidNumberDashName) {
-  StringPiece str = "-foo";
+  absl::string_view str = "-foo";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Unable to parse number.",
                 ParseErrorType::UNABLE_TO_PARSE_NUMBER);
@@ -577,7 +578,7 @@
 }
 
 TEST_F(JsonStreamParserTest, InvalidLiteralInArray) {
-  StringPiece str = "[nule]";
+  absl::string_view str = "[nule]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
     DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
@@ -585,7 +586,7 @@
 }
 
 TEST_F(JsonStreamParserTest, InvalidLiteralInObject) {
-  StringPiece str = "{123false}";
+  absl::string_view str = "{123false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected an object key or }.",
@@ -595,7 +596,7 @@
 
 // mismatched quotes failure on strings
 TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) {
-  StringPiece str = "'Some str\"";
+  absl::string_view str = "'Some str\"";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Closing quote expected in string.",
                 ParseErrorType::EXPECTED_CLOSING_QUOTE);
@@ -603,7 +604,7 @@
 }
 
 TEST_F(JsonStreamParserTest, MismatchedDoubleQuotedLiteral) {
-  StringPiece str = "\"Another string that ends poorly!'";
+  absl::string_view 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);
@@ -612,7 +613,7 @@
 
 // unterminated strings
 TEST_F(JsonStreamParserTest, UnterminatedLiteralString) {
-  StringPiece str = "\"Forgot the rest of i";
+  absl::string_view 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);
@@ -620,7 +621,7 @@
 }
 
 TEST_F(JsonStreamParserTest, UnterminatedStringEscape) {
-  StringPiece str = "\"Forgot the rest of \\";
+  absl::string_view 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);
@@ -628,7 +629,7 @@
 }
 
 TEST_F(JsonStreamParserTest, UnterminatedStringInArray) {
-  StringPiece str = "[\"Forgot to close the string]";
+  absl::string_view str = "[\"Forgot to close the string]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
     DoErrorTest(str, i, "Closing quote expected in string.",
@@ -637,7 +638,7 @@
 }
 
 TEST_F(JsonStreamParserTest, UnterminatedStringInObject) {
-  StringPiece str = "{f: \"Forgot to close the string}";
+  absl::string_view 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.",
@@ -646,7 +647,7 @@
 }
 
 TEST_F(JsonStreamParserTest, UnterminatedObject) {
-  StringPiece str = "{";
+  absl::string_view str = "{";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Unexpected end of string.",
@@ -657,7 +658,7 @@
 
 // mismatched object and array closing
 TEST_F(JsonStreamParserTest, MismatchedCloseObject) {
-  StringPiece str = "{'key': true]";
+  absl::string_view 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.",
@@ -666,7 +667,7 @@
 }
 
 TEST_F(JsonStreamParserTest, MismatchedCloseArray) {
-  StringPiece str = "[true, null}";
+  absl::string_view str = "[true, null}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderBool("", true)->RenderNull("");
     DoErrorTest(str, i, "Expected , or ] after array value.",
@@ -676,7 +677,7 @@
 
 // Invalid object keys.
 TEST_F(JsonStreamParserTest, InvalidNumericObjectKey) {
-  StringPiece str = "{42: true}";
+  absl::string_view str = "{42: true}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected an object key or }.",
@@ -685,7 +686,7 @@
 }
 
 TEST_F(JsonStreamParserTest, InvalidLiteralObjectInObject) {
-  StringPiece str = "{{bob: true}}";
+  absl::string_view str = "{{bob: true}}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected an object key or }.",
@@ -694,7 +695,7 @@
 }
 
 TEST_F(JsonStreamParserTest, InvalidLiteralArrayInObject) {
-  StringPiece str = "{[null]}";
+  absl::string_view str = "{[null]}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected an object key or }.",
@@ -703,7 +704,7 @@
 }
 
 TEST_F(JsonStreamParserTest, InvalidLiteralValueInObject) {
-  StringPiece str = "{false}";
+  absl::string_view str = "{false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected an object key or }.",
@@ -712,7 +713,7 @@
 }
 
 TEST_F(JsonStreamParserTest, MissingColonAfterStringInObject) {
-  StringPiece str = "{\"key\"}";
+  absl::string_view str = "{\"key\"}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected : between key:value pair.",
@@ -721,7 +722,7 @@
 }
 
 TEST_F(JsonStreamParserTest, MissingColonAfterKeyInObject) {
-  StringPiece str = "{key}";
+  absl::string_view str = "{key}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected : between key:value pair.",
@@ -730,7 +731,7 @@
 }
 
 TEST_F(JsonStreamParserTest, EndOfTextAfterKeyInObject) {
-  StringPiece str = "{key";
+  absl::string_view str = "{key";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Unexpected end of string.",
@@ -739,7 +740,7 @@
 }
 
 TEST_F(JsonStreamParserTest, MissingValueAfterColonInObject) {
-  StringPiece str = "{key:}";
+  absl::string_view str = "{key:}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
@@ -747,7 +748,7 @@
 }
 
 TEST_F(JsonStreamParserTest, MissingCommaBetweenObjectEntries) {
-  StringPiece str = "{key:20 'hello': true}";
+  absl::string_view 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.",
@@ -756,7 +757,7 @@
 }
 
 TEST_F(JsonStreamParserTest, InvalidLiteralAsObjectKey) {
-  StringPiece str = "{false: 20}";
+  absl::string_view str = "{false: 20}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected an object key or }.",
@@ -765,7 +766,7 @@
 }
 
 TEST_F(JsonStreamParserTest, ExtraCharactersAfterObject) {
-  StringPiece str = "{}}";
+  absl::string_view str = "{}}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->EndObject();
     DoErrorTest(str, i, "Parsing terminated before end of input.",
@@ -774,7 +775,7 @@
 }
 
 TEST_F(JsonStreamParserTest, PositiveNumberTooBigIsDouble) {
-  StringPiece str = "18446744073709551616";  // 2^64
+  absl::string_view str = "18446744073709551616";  // 2^64
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderDouble("", 18446744073709552000.0);
     DoTest(str, i);
@@ -782,7 +783,7 @@
 }
 
 TEST_F(JsonStreamParserTest, NegativeNumberTooBigIsDouble) {
-  StringPiece str = "-18446744073709551616";
+  absl::string_view str = "-18446744073709551616";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderDouble("", -18446744073709551616.0);
     DoTest(str, i);
@@ -790,7 +791,7 @@
 }
 
 TEST_F(JsonStreamParserTest, DoubleTooBig) {
-  StringPiece str = "[1.89769e+308]";
+  absl::string_view str = "[1.89769e+308]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
     DoErrorTest(str, i, "Number exceeds the range of double.",
@@ -807,7 +808,7 @@
 
 // invalid bare backslash.
 TEST_F(JsonStreamParserTest, UnfinishedEscape) {
-  StringPiece str = "\"\\";
+  absl::string_view str = "\"\\";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Closing quote expected in string.",
                 ParseErrorType::EXPECTED_CLOSING_QUOTE);
@@ -816,7 +817,7 @@
 
 // invalid bare backslash u.
 TEST_F(JsonStreamParserTest, UnfinishedUnicodeEscape) {
-  StringPiece str = "\"\\u";
+  absl::string_view str = "\"\\u";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Illegal hex string.",
                 ParseErrorType::ILLEGAL_HEX_STRING);
@@ -825,7 +826,7 @@
 
 // invalid unicode sequence.
 TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
-  StringPiece str = "\"\\u12";
+  absl::string_view str = "\"\\u12";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Illegal hex string.",
                 ParseErrorType::ILLEGAL_HEX_STRING);
@@ -834,7 +835,7 @@
 
 // invalid unicode sequence (valid in modern EcmaScript but not in JSON).
 TEST_F(JsonStreamParserTest, BracketedUnicodeEscape) {
-  StringPiece str = "\"\\u{1f36f}\"";
+  absl::string_view str = "\"\\u{1f36f}\"";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Invalid escape sequence.",
                 ParseErrorType::INVALID_ESCAPE_SEQUENCE);
@@ -843,7 +844,7 @@
 
 
 TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
-  StringPiece str = "\"\\u12$4hello";
+  absl::string_view str = "\"\\u12$4hello";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Invalid escape sequence.",
                 ParseErrorType::INVALID_ESCAPE_SEQUENCE);
@@ -852,7 +853,7 @@
 
 // invalid unicode sequence in low half surrogate: g is not a hex digit.
 TEST_F(JsonStreamParserTest, UnicodeEscapeLowHalfSurrogateInvalidCharacters) {
-  StringPiece str = "\"\\ud800\\udcfg\"";
+  absl::string_view str = "\"\\ud800\\udcfg\"";
   for (int i = 0; i <= str.length(); ++i) {
     DoErrorTest(str, i, "Invalid escape sequence.",
                 ParseErrorType::INVALID_ESCAPE_SEQUENCE);
@@ -861,7 +862,7 @@
 
 // Extra commas with an object or array.
 TEST_F(JsonStreamParserTest, ExtraCommaInObject) {
-  StringPiece str = "{'k1': true,,'k2': false}";
+  absl::string_view 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 }.",
@@ -870,7 +871,7 @@
 }
 
 TEST_F(JsonStreamParserTest, ExtraCommaInArray) {
-  StringPiece str = "[true,,false}";
+  absl::string_view str = "[true,,false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderBool("", true);
     DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
@@ -879,7 +880,7 @@
 
 // Extra text beyond end of value.
 TEST_F(JsonStreamParserTest, ExtraTextAfterLiteral) {
-  StringPiece str = "'hello', 'world'";
+  absl::string_view str = "'hello', 'world'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderString("", "hello");
     DoErrorTest(str, i, "Parsing terminated before end of input.",
@@ -888,7 +889,7 @@
 }
 
 TEST_F(JsonStreamParserTest, ExtraTextAfterObject) {
-  StringPiece str = "{'key': true} 'oops'";
+  absl::string_view 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.",
@@ -897,7 +898,7 @@
 }
 
 TEST_F(JsonStreamParserTest, ExtraTextAfterArray) {
-  StringPiece str = "[null] 'oops'";
+  absl::string_view str = "[null] 'oops'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderNull("")->EndList();
     DoErrorTest(str, i, "Parsing terminated before end of input.",
@@ -907,14 +908,14 @@
 
 // Random unknown text in the value.
 TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) {
-  StringPiece str = "*&#25";
+  absl::string_view 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]";
+  absl::string_view str = "[*&#25]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
     DoErrorTest(str, i, "Expected a value or ] within an array.",
@@ -923,7 +924,7 @@
 }
 
 TEST_F(JsonStreamParserTest, UnknownCharactersInObject) {
-  StringPiece str = "{'key': *&#25}";
+  absl::string_view str = "{'key': *&#25}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
     DoErrorTest(str, i, "Expected a value.", ParseErrorType::EXPECTED_VALUE);
@@ -934,11 +935,11 @@
   int count = 99;
   std::string str;
   for (int i = 0; i < count; ++i) {
-    StrAppend(&str, "{'a':");
+    absl::StrAppend(&str, "{'a':");
   }
-  StrAppend(&str, "{'nest64':'v1', 'nest64': false, 'nest64': ['v2']}");
+  absl::StrAppend(&str, "{'nest64':'v1', 'nest64': false, 'nest64': ['v2']}");
   for (int i = 0; i < count; ++i) {
-    StrAppend(&str, "}");
+    absl::StrAppend(&str, "}");
   }
   ow_.StartObject("");
   for (int i = 0; i < count; ++i) {
@@ -960,14 +961,14 @@
   int count = 98;
   std::string str;
   for (int i = 0; i < count; ++i) {
-    StrAppend(&str, "{'a':");
+    absl::StrAppend(&str, "{'a':");
   }
   // Supports trailing commas.
-  StrAppend(&str,
+  absl::StrAppend(&str,
                   "{'nest11' : [{'nest12' : null,},],"
                   "'nest21' : {'nest22' : {'nest23' : false}}}");
   for (int i = 0; i < count; ++i) {
-    StrAppend(&str, "}");
+    absl::StrAppend(&str, "}");
   }
   DoErrorTest(str, 0,
               "Message too deep. Max recursion depth reached for key 'nest22'");
diff --git a/src/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/util/internal/location_tracker.h
index 68fefcc..4cec03e 100644
--- a/src/google/protobuf/util/internal/location_tracker.h
+++ b/src/google/protobuf/util/internal/location_tracker.h
@@ -33,10 +33,10 @@
 
 #include <string>
 
-#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 {
@@ -47,6 +47,8 @@
 // the location information for the purpose of error reporting.
 class PROTOBUF_EXPORT LocationTrackerInterface {
  public:
+  LocationTrackerInterface(const LocationTrackerInterface&) = delete;
+  LocationTrackerInterface& operator=(const LocationTrackerInterface&) = delete;
   virtual ~LocationTrackerInterface() {}
 
   // Returns the object location as human readable string.
@@ -57,7 +59,6 @@
 
  private:
   // Please do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface);
 };
 
 }  // namespace converter
@@ -65,6 +66,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__
diff --git a/src/google/protobuf/util/internal/mock_error_listener.h b/src/google/protobuf/util/internal/mock_error_listener.h
index 3fbdd88..b04de6f 100644
--- a/src/google/protobuf/util/internal/mock_error_listener.h
+++ b/src/google/protobuf/util/internal/mock_error_listener.h
@@ -32,9 +32,9 @@
 #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>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/util/internal/error_listener.h"
+#include "google/protobuf/util/internal/location_tracker.h"
 
 namespace google {
 namespace protobuf {
@@ -48,15 +48,15 @@
 
   MOCK_METHOD(void, InvalidName,
               (const LocationTrackerInterface& loc,
-               StringPiece unknown_name, StringPiece message),
+               absl::string_view unknown_name, absl::string_view message),
               (override));
   MOCK_METHOD(void, InvalidValue,
-              (const LocationTrackerInterface& loc, StringPiece type_name,
-               StringPiece value),
+              (const LocationTrackerInterface& loc, absl::string_view type_name,
+               absl::string_view value),
               (override));
   MOCK_METHOD(void, MissingField,
               (const LocationTrackerInterface& loc,
-               StringPiece missing_name),
+               absl::string_view missing_name),
               (override));
 };
 
diff --git a/src/google/protobuf/util/internal/object_location_tracker.h b/src/google/protobuf/util/internal/object_location_tracker.h
index 47821e6..c5a8f27 100644
--- a/src/google/protobuf/util/internal/object_location_tracker.h
+++ b/src/google/protobuf/util/internal/object_location_tracker.h
@@ -33,8 +33,8 @@
 
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/util/internal/location_tracker.h>
+#include "google/protobuf/port.h"
+#include "google/protobuf/util/internal/location_tracker.h"
 
 namespace google {
 namespace protobuf {
@@ -46,14 +46,13 @@
  public:
   // Creates an empty location tracker.
   ObjectLocationTracker() {}
+  ObjectLocationTracker(const ObjectLocationTracker&) = delete;
+  ObjectLocationTracker& operator=(const ObjectLocationTracker&) = delete;
 
   ~ObjectLocationTracker() override {}
 
   // Returns empty because nothing is tracked.
   std::string ToString() const override { return ""; }
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker);
 };
 
 }  // namespace converter
diff --git a/src/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h
index fc7672e..2538314 100644
--- a/src/google/protobuf/util/internal/object_source.h
+++ b/src/google/protobuf/util/internal/object_source.h
@@ -31,13 +31,13 @@
 #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>
+#include "absl/status/status.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 {
@@ -54,25 +54,23 @@
 // Derived classes could be thread-unsafe.
 class PROTOBUF_EXPORT ObjectSource {
  public:
+  ObjectSource(const ObjectSource&) = delete;
+  ObjectSource& operator=(const ObjectSource&) = delete;
   virtual ~ObjectSource() {}
 
   // Writes to the ObjectWriter
-  virtual util::Status WriteTo(ObjectWriter* ow) const {
+  virtual absl::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,
+  virtual absl::Status NamedWriteTo(absl::string_view name,
                                     ObjectWriter* ow) const = 0;
 
  protected:
   ObjectSource() {}
-
- private:
-  // Do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource);
 };
 
 }  // namespace converter
@@ -80,6 +78,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 4dabd37..c03c195 100644
--- a/src/google/protobuf/util/internal/object_writer.cc
+++ b/src/google/protobuf/util/internal/object_writer.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/util/internal/object_writer.h>
+#include "google/protobuf/util/internal/object_writer.h"
 
-#include <google/protobuf/util/internal/datapiece.h>
+#include "google/protobuf/util/internal/datapiece.h"
 
 namespace google {
 namespace protobuf {
@@ -39,7 +39,7 @@
 
 // static
 void ObjectWriter::RenderDataPieceTo(const DataPiece& data,
-                                     StringPiece name, ObjectWriter* ow) {
+                                     absl::string_view name, ObjectWriter* ow) {
   switch (data.type()) {
     case DataPiece::TYPE_INT32: {
       ow->RenderInt32(name, data.ToInt32().value());
diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h
index bc4095b..a91c628 100644
--- a/src/google/protobuf/util/internal/object_writer.h
+++ b/src/google/protobuf/util/internal/object_writer.h
@@ -33,11 +33,12 @@
 
 #include <cstdint>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/port.h"
+#include "absl/strings/string_view.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -63,56 +64,59 @@
 // and get rid the need to call EndXXX().
 class PROTOBUF_EXPORT ObjectWriter {
  public:
+  ObjectWriter(const ObjectWriter&) = delete;
+  ObjectWriter& operator=(const ObjectWriter&) = delete;
   virtual ~ObjectWriter() {}
 
   // Starts an object. If the name is empty, the object will not be named.
-  virtual ObjectWriter* StartObject(StringPiece name) = 0;
+  virtual ObjectWriter* StartObject(absl::string_view 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;
+  virtual ObjectWriter* StartList(absl::string_view name) = 0;
 
   // Ends a list.
   virtual ObjectWriter* EndList() = 0;
 
   // Renders a boolean value.
-  virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0;
+  virtual ObjectWriter* RenderBool(absl::string_view name, bool value) = 0;
 
   // Renders an 32-bit integer value.
-  virtual ObjectWriter* RenderInt32(StringPiece name, int32_t value) = 0;
+  virtual ObjectWriter* RenderInt32(absl::string_view name, int32_t value) = 0;
 
   // Renders an 32-bit unsigned integer value.
-  virtual ObjectWriter* RenderUint32(StringPiece name,
+  virtual ObjectWriter* RenderUint32(absl::string_view name,
                                      uint32_t value) = 0;
 
   // Renders a 64-bit integer value.
-  virtual ObjectWriter* RenderInt64(StringPiece name, int64_t value) = 0;
+  virtual ObjectWriter* RenderInt64(absl::string_view name, int64_t value) = 0;
 
   // Renders an 64-bit unsigned integer value.
-  virtual ObjectWriter* RenderUint64(StringPiece name,
+  virtual ObjectWriter* RenderUint64(absl::string_view name,
                                      uint64_t value) = 0;
 
 
   // Renders a double value.
-  virtual ObjectWriter* RenderDouble(StringPiece name, double value) = 0;
+  virtual ObjectWriter* RenderDouble(absl::string_view name, double value) = 0;
   // Renders a float value.
-  virtual ObjectWriter* RenderFloat(StringPiece name, float value) = 0;
+  virtual ObjectWriter* RenderFloat(absl::string_view name, float value) = 0;
 
-  // Renders a StringPiece value. This is for rendering strings.
-  virtual ObjectWriter* RenderString(StringPiece name,
-                                     StringPiece value) = 0;
+  // Renders a string value.
+  virtual ObjectWriter* RenderString(absl::string_view name,
+                                     absl::string_view value) = 0;
 
   // Renders a bytes value.
-  virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0;
+  virtual ObjectWriter* RenderBytes(absl::string_view name,
+                                    absl::string_view value) = 0;
 
   // Renders a Null value.
-  virtual ObjectWriter* RenderNull(StringPiece name) = 0;
+  virtual ObjectWriter* RenderNull(absl::string_view name) = 0;
 
 
   // Renders a DataPiece object to a ObjectWriter.
-  static void RenderDataPieceTo(const DataPiece& data, StringPiece name,
+  static void RenderDataPieceTo(const DataPiece& data, absl::string_view name,
                                 ObjectWriter* ow);
 
 
@@ -136,9 +140,6 @@
   // 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
@@ -146,6 +147,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index afa5e2e..7924437 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -28,27 +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/proto_writer.h>
+#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>
+#include "google/protobuf/wire_format_lite.h"
+#include "absl/base/call_once.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/time/clock.h"
+#include "absl/time/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"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -73,7 +75,6 @@
       element_(nullptr),
       size_insert_(),
       output_(output),
-      buffer_(),
       adapter_(&buffer_),
       stream_(new CodedOutputStream(&adapter_)),
       listener_(listener),
@@ -95,7 +96,6 @@
       element_(nullptr),
       size_insert_(),
       output_(output),
-      buffer_(),
       adapter_(&buffer_),
       stream_(new CodedOutputStream(&adapter_)),
       listener_(listener),
@@ -121,9 +121,9 @@
 namespace {
 
 // Writes an INT32 field, including tag to the stream.
-inline util::Status WriteInt32(int field_number, const DataPiece& data,
+inline absl::Status WriteInt32(int field_number, const DataPiece& data,
                                CodedOutputStream* stream) {
-  util::StatusOr<int32_t> i32 = data.ToInt32();
+  absl::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteInt32(field_number, i32.value(), stream);
   }
@@ -131,9 +131,9 @@
 }
 
 // writes an SFIXED32 field, including tag, to the stream.
-inline util::Status WriteSFixed32(int field_number, const DataPiece& data,
+inline absl::Status WriteSFixed32(int field_number, const DataPiece& data,
                                   CodedOutputStream* stream) {
-  util::StatusOr<int32_t> i32 = data.ToInt32();
+  absl::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteSFixed32(field_number, i32.value(), stream);
   }
@@ -141,9 +141,9 @@
 }
 
 // Writes an SINT32 field, including tag, to the stream.
-inline util::Status WriteSInt32(int field_number, const DataPiece& data,
+inline absl::Status WriteSInt32(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<int32_t> i32 = data.ToInt32();
+  absl::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteSInt32(field_number, i32.value(), stream);
   }
@@ -151,9 +151,9 @@
 }
 
 // Writes a FIXED32 field, including tag, to the stream.
-inline util::Status WriteFixed32(int field_number, const DataPiece& data,
+inline absl::Status WriteFixed32(int field_number, const DataPiece& data,
                                  CodedOutputStream* stream) {
-  util::StatusOr<uint32_t> u32 = data.ToUint32();
+  absl::StatusOr<uint32_t> u32 = data.ToUint32();
   if (u32.ok()) {
     WireFormatLite::WriteFixed32(field_number, u32.value(), stream);
   }
@@ -161,9 +161,9 @@
 }
 
 // Writes a UINT32 field, including tag, to the stream.
-inline util::Status WriteUInt32(int field_number, const DataPiece& data,
+inline absl::Status WriteUInt32(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<uint32_t> u32 = data.ToUint32();
+  absl::StatusOr<uint32_t> u32 = data.ToUint32();
   if (u32.ok()) {
     WireFormatLite::WriteUInt32(field_number, u32.value(), stream);
   }
@@ -171,9 +171,9 @@
 }
 
 // Writes an INT64 field, including tag, to the stream.
-inline util::Status WriteInt64(int field_number, const DataPiece& data,
+inline absl::Status WriteInt64(int field_number, const DataPiece& data,
                                CodedOutputStream* stream) {
-  util::StatusOr<int64_t> i64 = data.ToInt64();
+  absl::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteInt64(field_number, i64.value(), stream);
   }
@@ -181,9 +181,9 @@
 }
 
 // Writes an SFIXED64 field, including tag, to the stream.
-inline util::Status WriteSFixed64(int field_number, const DataPiece& data,
+inline absl::Status WriteSFixed64(int field_number, const DataPiece& data,
                                   CodedOutputStream* stream) {
-  util::StatusOr<int64_t> i64 = data.ToInt64();
+  absl::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteSFixed64(field_number, i64.value(), stream);
   }
@@ -191,9 +191,9 @@
 }
 
 // Writes an SINT64 field, including tag, to the stream.
-inline util::Status WriteSInt64(int field_number, const DataPiece& data,
+inline absl::Status WriteSInt64(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<int64_t> i64 = data.ToInt64();
+  absl::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteSInt64(field_number, i64.value(), stream);
   }
@@ -201,9 +201,9 @@
 }
 
 // Writes a FIXED64 field, including tag, to the stream.
-inline util::Status WriteFixed64(int field_number, const DataPiece& data,
+inline absl::Status WriteFixed64(int field_number, const DataPiece& data,
                                  CodedOutputStream* stream) {
-  util::StatusOr<uint64_t> u64 = data.ToUint64();
+  absl::StatusOr<uint64_t> u64 = data.ToUint64();
   if (u64.ok()) {
     WireFormatLite::WriteFixed64(field_number, u64.value(), stream);
   }
@@ -211,9 +211,9 @@
 }
 
 // Writes a UINT64 field, including tag, to the stream.
-inline util::Status WriteUInt64(int field_number, const DataPiece& data,
+inline absl::Status WriteUInt64(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<uint64_t> u64 = data.ToUint64();
+  absl::StatusOr<uint64_t> u64 = data.ToUint64();
   if (u64.ok()) {
     WireFormatLite::WriteUInt64(field_number, u64.value(), stream);
   }
@@ -221,9 +221,9 @@
 }
 
 // Writes a DOUBLE field, including tag, to the stream.
-inline util::Status WriteDouble(int field_number, const DataPiece& data,
+inline absl::Status WriteDouble(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<double> d = data.ToDouble();
+  absl::StatusOr<double> d = data.ToDouble();
   if (d.ok()) {
     WireFormatLite::WriteDouble(field_number, d.value(), stream);
   }
@@ -231,9 +231,9 @@
 }
 
 // Writes a FLOAT field, including tag, to the stream.
-inline util::Status WriteFloat(int field_number, const DataPiece& data,
+inline absl::Status WriteFloat(int field_number, const DataPiece& data,
                                CodedOutputStream* stream) {
-  util::StatusOr<float> f = data.ToFloat();
+  absl::StatusOr<float> f = data.ToFloat();
   if (f.ok()) {
     WireFormatLite::WriteFloat(field_number, f.value(), stream);
   }
@@ -241,9 +241,9 @@
 }
 
 // Writes a BOOL field, including tag, to the stream.
-inline util::Status WriteBool(int field_number, const DataPiece& data,
+inline absl::Status WriteBool(int field_number, const DataPiece& data,
                               CodedOutputStream* stream) {
-  util::StatusOr<bool> b = data.ToBool();
+  absl::StatusOr<bool> b = data.ToBool();
   if (b.ok()) {
     WireFormatLite::WriteBool(field_number, b.value(), stream);
   }
@@ -251,9 +251,9 @@
 }
 
 // Writes a BYTES field, including tag, to the stream.
-inline util::Status WriteBytes(int field_number, const DataPiece& data,
+inline absl::Status WriteBytes(int field_number, const DataPiece& data,
                                CodedOutputStream* stream) {
-  util::StatusOr<std::string> c = data.ToBytes();
+  absl::StatusOr<std::string> c = data.ToBytes();
   if (c.ok()) {
     WireFormatLite::WriteBytes(field_number, c.value(), stream);
   }
@@ -261,9 +261,9 @@
 }
 
 // Writes a STRING field, including tag, to the stream.
-inline util::Status WriteString(int field_number, const DataPiece& data,
+inline absl::Status WriteString(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<std::string> s = data.ToString();
+  absl::StatusOr<std::string> s = data.ToString();
   if (s.ok()) {
     WireFormatLite::WriteString(field_number, s.value(), stream);
   }
@@ -410,22 +410,22 @@
       std::string name = now->parent_field_->name();
       int i = 0;
       while (i < name.size() &&
-             (ascii_isalnum(name[i]) || name[i] == '_'))
+             (absl::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);
+          absl::StrAppend(&loc, ".", name);
         }
       } else {
-        StrAppend(&loc, "[\"", CEscape(name), "\"]");
+        absl::StrAppend(&loc, "[\"", absl::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, "]");
+      absl::StrAppend(&loc, "[", array_index_now - 1, "]");
     }
   }
 
@@ -440,22 +440,22 @@
   oneof_indices_[index] = true;
 }
 
-void ProtoWriter::InvalidName(StringPiece unknown_name,
-                              StringPiece message) {
+void ProtoWriter::InvalidName(absl::string_view unknown_name,
+                              absl::string_view message) {
   listener_->InvalidName(location(), unknown_name, message);
 }
 
-void ProtoWriter::InvalidValue(StringPiece type_name,
-                               StringPiece value) {
+void ProtoWriter::InvalidValue(absl::string_view type_name,
+                               absl::string_view value) {
   listener_->InvalidValue(location(), type_name, value);
 }
 
-void ProtoWriter::MissingField(StringPiece missing_name) {
+void ProtoWriter::MissingField(absl::string_view missing_name) {
   listener_->MissingField(location(), missing_name);
 }
 
 ProtoWriter* ProtoWriter::StartObject(
-    StringPiece name) {
+    absl::string_view name) {
   // Starting the root message. Create the root ProtoElement and return.
   if (element_ == nullptr) {
     if (!name.empty()) {
@@ -479,7 +479,7 @@
   const google::protobuf::Type* type = LookupType(field);
   if (type == nullptr) {
     ++invalid_depth_;
-    InvalidName(name, StrCat("Missing descriptor for field: ",
+    InvalidName(name, absl::StrCat("Missing descriptor for field: ",
                                    field->type_url()));
     return this;
   }
@@ -508,7 +508,7 @@
 }
 
 ProtoWriter* ProtoWriter::StartList(
-    StringPiece name) {
+    absl::string_view name) {
 
   const google::protobuf::Field* field = BeginNamed(name, true);
 
@@ -522,7 +522,7 @@
   const google::protobuf::Type* type = LookupType(field);
   if (type == nullptr) {
     ++invalid_depth_;
-    InvalidName(name, StrCat("Missing descriptor for field: ",
+    InvalidName(name, absl::StrCat("Missing descriptor for field: ",
                                    field->type_url()));
     return this;
   }
@@ -541,8 +541,8 @@
 }
 
 ProtoWriter* ProtoWriter::RenderDataPiece(
-    StringPiece name, const DataPiece& data) {
-  util::Status status;
+    absl::string_view name, const DataPiece& data) {
+  absl::Status status;
   if (invalid_depth_ > 0) return this;
 
   const google::protobuf::Field* field = Lookup(name);
@@ -553,7 +553,7 @@
 
   const google::protobuf::Type* type = LookupType(field);
   if (type == nullptr) {
-    InvalidName(name, StrCat("Missing descriptor for field: ",
+    InvalidName(name, absl::StrCat("Missing descriptor for field: ",
                                    field->type_url()));
     return this;
   }
@@ -562,14 +562,14 @@
 }
 
 bool ProtoWriter::ValidOneof(const google::protobuf::Field& field,
-                             StringPiece unnormalized_name) {
+                             absl::string_view unnormalized_name) {
   if (element_ == nullptr) return true;
 
   if (field.oneof_index() > 0) {
     if (element_->IsOneofIndexTaken(field.oneof_index())) {
       InvalidValue(
           "oneof",
-          StrCat(
+          absl::StrCat(
               "oneof field '", element_->type().oneofs(field.oneof_index() - 1),
               "' is already set. Cannot set '", unnormalized_name, "'"));
       return false;
@@ -596,14 +596,14 @@
   return this;
 }
 
-util::Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data,
+absl::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(
+  absl::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) {
@@ -615,7 +615,7 @@
 ProtoWriter* ProtoWriter::RenderPrimitiveField(
     const google::protobuf::Field& field, const google::protobuf::Type& type,
     const DataPiece& data) {
-  util::Status status;
+  absl::Status status;
 
   // Pushing a ProtoElement and then pop it off at the end for 2 purposes:
   // error location reporting and required field accounting.
@@ -695,7 +695,7 @@
       break;
     }
     default:  // TYPE_GROUP, TYPE_MESSAGE, TYPE_UNKNOWN.
-      status = util::InvalidArgumentError(data.ValueAsStringOrDefault(""));
+      status = absl::InvalidArgumentError(data.ValueAsStringOrDefault(""));
   }
 
   if (!status.ok()) {
@@ -716,7 +716,7 @@
   return this;
 }
 
-const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name,
+const google::protobuf::Field* ProtoWriter::BeginNamed(absl::string_view name,
                                                        bool is_list) {
   if (invalid_depth_ > 0) {
     ++invalid_depth_;
@@ -737,7 +737,7 @@
 }
 
 const google::protobuf::Field* ProtoWriter::Lookup(
-    StringPiece unnormalized_name) {
+    absl::string_view unnormalized_name) {
   ProtoElement* e = element();
   if (e == nullptr) {
     InvalidName(unnormalized_name, "Root element must be a message.");
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
index a7cf6ac..f19b191 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -37,23 +37,22 @@
 #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>
+#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 "absl/status/status.h"
+#include "google/protobuf/port.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"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -74,53 +73,57 @@
 // 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() = delete;
+  ProtoWriter(const ProtoWriter&) = delete;
+  ProtoWriter& operator=(const ProtoWriter&) = delete;
   ~ProtoWriter() override;
 
   // ObjectWriter methods.
-  ProtoWriter* StartObject(StringPiece name) override;
+  ProtoWriter* StartObject(absl::string_view name) override;
   ProtoWriter* EndObject() override;
-  ProtoWriter* StartList(StringPiece name) override;
+  ProtoWriter* StartList(absl::string_view name) override;
   ProtoWriter* EndList() override;
-  ProtoWriter* RenderBool(StringPiece name, bool value) override {
+  ProtoWriter* RenderBool(absl::string_view name, bool value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderInt32(StringPiece name, int32_t value) override {
+  ProtoWriter* RenderInt32(absl::string_view name, int32_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderUint32(StringPiece name, uint32_t value) override {
+  ProtoWriter* RenderUint32(absl::string_view name, uint32_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderInt64(StringPiece name, int64_t value) override {
+  ProtoWriter* RenderInt64(absl::string_view name, int64_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderUint64(StringPiece name, uint64_t value) override {
+  ProtoWriter* RenderUint64(absl::string_view name, uint64_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderDouble(StringPiece name, double value) override {
+  ProtoWriter* RenderDouble(absl::string_view name, double value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderFloat(StringPiece name, float value) override {
+  ProtoWriter* RenderFloat(absl::string_view name, float value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderString(StringPiece name,
-                            StringPiece value) override {
+  ProtoWriter* RenderString(absl::string_view name,
+                            absl::string_view value) override {
     return RenderDataPiece(name,
                            DataPiece(value, use_strict_base64_decoding()));
   }
 
-  ProtoWriter* RenderBytes(StringPiece name, StringPiece value) override {
+  ProtoWriter* RenderBytes(absl::string_view name,
+                           absl::string_view value) override {
     return RenderDataPiece(
         name, DataPiece(value, false, use_strict_base64_decoding()));
   }
 
-  ProtoWriter* RenderNull(StringPiece name) override {
+  ProtoWriter* RenderNull(absl::string_view 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,
+  virtual ProtoWriter* RenderDataPiece(absl::string_view name,
                                        const DataPiece& data);
 
 
@@ -178,6 +181,9 @@
     // Constructor for a field of an element.
     ProtoElement(ProtoElement* parent, const google::protobuf::Field* field,
                  const google::protobuf::Type& type, bool is_list);
+    ProtoElement() = delete;
+    ProtoElement(const ProtoElement&) = delete;
+    ProtoElement& operator=(const ProtoElement&) = delete;
 
     ~ProtoElement() override {}
 
@@ -245,8 +251,6 @@
     // 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.
@@ -261,20 +265,20 @@
   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);
+  void InvalidName(absl::string_view unknown_name, absl::string_view message);
+  void InvalidValue(absl::string_view type_name, absl::string_view value);
+  void MissingField(absl::string_view missing_name);
 
   // Common code for BeginObject() and BeginList() that does invalid_depth_
   // bookkeeping associated with name lookup.
-  const google::protobuf::Field* BeginNamed(StringPiece name,
+  const google::protobuf::Field* BeginNamed(absl::string_view 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);
+  const google::protobuf::Field* Lookup(absl::string_view name);
 
   // Lookup the field type in the type descriptor. Returns nullptr if the type
   // is not known.
@@ -296,7 +300,7 @@
   // 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);
+                  absl::string_view unnormalized_name);
 
   // Returns true if the field is repeated.
   bool IsRepeated(const google::protobuf::Field& field);
@@ -316,7 +320,7 @@
 
  private:
   // Writes an ENUM field, including tag, to the stream.
-  static util::Status WriteEnum(int field_number, const DataPiece& data,
+  static absl::Status WriteEnum(int field_number, const DataPiece& data,
                                 const google::protobuf::Enum* enum_type,
                                 io::CodedOutputStream* stream,
                                 bool use_lower_camel_for_enums,
@@ -375,8 +379,6 @@
   ErrorListener* listener_;
   int invalid_depth_;
   std::unique_ptr<LocationTrackerInterface> tracker_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoWriter);
 };
 
 }  // namespace converter
@@ -384,6 +386,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index cf6c99a..63a9dc1 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -28,35 +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/util/internal/protostream_objectsource.h>
+#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>
+#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/unknown_field_set.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/base/call_once.h"
+#include "absl/base/casts.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/stubs/stringprintf.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/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/status_macros.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 
 namespace google {
@@ -83,9 +84,9 @@
     const google::protobuf::Enum& tech_enum, int number);
 
 // Utility function to format nanos.
-const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros);
+std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros);
 
-util::StatusOr<std::string> MapKeyDefaultValueAsString(
+absl::StatusOr<std::string> MapKeyDefaultValueAsString(
     const google::protobuf::Field& field) {
   switch (field.kind()) {
     case google::protobuf::Field::TYPE_BOOL:
@@ -104,7 +105,7 @@
     case google::protobuf::Field::TYPE_STRING:
       return std::string();
     default:
-      return util::InternalError("Invalid map key type.");
+      return absl::InternalError("Invalid map key type.");
   }
 }
 }  // namespace
@@ -142,7 +143,7 @@
   }
 }
 
-util::Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name,
+absl::Status ProtoStreamObjectSource::NamedWriteTo(absl::string_view name,
                                                    ObjectWriter* ow) const {
   return WriteMessage(type_, name, 0, true, ow);
 }
@@ -167,8 +168,8 @@
   return field;
 }
 
-util::Status ProtoStreamObjectSource::WriteMessage(
-    const google::protobuf::Type& type, StringPiece name,
+absl::Status ProtoStreamObjectSource::WriteMessage(
+    const google::protobuf::Type& type, absl::string_view name,
     const uint32_t end_tag, bool include_start_and_end,
     ObjectWriter* ow) const {
 
@@ -228,11 +229,11 @@
   if (include_start_and_end) {
     ow->EndObject();
   }
-  return util::Status();
+  return absl::Status();
 }
 
-util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderList(
-    const google::protobuf::Field* field, StringPiece name,
+absl::StatusOr<uint32_t> ProtoStreamObjectSource::RenderList(
+    const google::protobuf::Field* field, absl::string_view name,
     uint32_t list_tag, ObjectWriter* ow) const {
   uint32_t tag_to_return = 0;
   ow->StartList(name);
@@ -253,8 +254,8 @@
   return tag_to_return;
 }
 
-util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderMap(
-    const google::protobuf::Field* field, StringPiece /* name */,
+absl::StatusOr<uint32_t> ProtoStreamObjectSource::RenderMap(
+    const google::protobuf::Field* field, absl::string_view /* name */,
     uint32_t list_tag, ObjectWriter* ow) const {
   const google::protobuf::Type* field_type =
       typeinfo_->GetTypeByTypeUrl(field->type_url());
@@ -284,7 +285,7 @@
           if (key_field == nullptr) {
             // The Type info for this map entry is incorrect. It should always
             // have a field named "key" and with field number 1.
-            return util::InternalError("Invalid map entry.");
+            return absl::InternalError("Invalid map entry.");
           }
           ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field));
         }
@@ -292,7 +293,7 @@
       } 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.");
+        return absl::InternalError("Invalid map entry.");
       }
     }
     stream_->PopLimit(old_limit);
@@ -300,61 +301,69 @@
   return tag_to_return;
 }
 
-util::Status ProtoStreamObjectSource::RenderPacked(
+absl::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));
+    RETURN_IF_ERROR(RenderField(field, absl::string_view(), ow));
   }
   stream_->PopLimit(old_limit);
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderTimestamp(
+absl::Status ProtoStreamObjectSource::RenderTimestamp(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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(
+    return absl::InternalError(absl::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));
+    return absl::InternalError(
+        absl::StrCat("Timestamp nanos exceeds limit for field: ", field_name));
   }
 
-  ow->RenderString(field_name,
-                   ::google::protobuf::internal::FormatTime(seconds, nanos));
-
-  return util::Status();
+  absl::Time tm = absl::FromUnixSeconds(seconds);
+  std::string formatted_seconds =
+      absl::FormatTime(kRfc3339TimeFormat, tm, absl::UTCTimeZone());
+  std::string formatted_time = StringPrintf(
+      "%s%sZ", formatted_seconds.c_str(),
+      FormatNanos(
+          nanos,
+          false
+          )
+          .c_str());
+  ow->RenderString(field_name, formatted_time);
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderDuration(
+absl::Status ProtoStreamObjectSource::RenderDuration(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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));
+    return absl::InternalError(
+        absl::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));
+    return absl::InternalError(
+        absl::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 "
+      return absl::InternalError(
+          absl::StrCat("Duration nanos is non-negative, but seconds is "
                        "negative for field: ",
                        field_name));
     }
@@ -373,90 +382,90 @@
           )
           .c_str());
   ow->RenderString(field_name, formatted_duration);
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderDouble(
+absl::Status ProtoStreamObjectSource::RenderDouble(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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();
+  ow->RenderDouble(field_name, absl::bit_cast<double>(buffer64));
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderFloat(
+absl::Status ProtoStreamObjectSource::RenderFloat(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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();
+  ow->RenderFloat(field_name, absl::bit_cast<float>(buffer32));
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderInt64(
+absl::Status ProtoStreamObjectSource::RenderInt64(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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();
+  ow->RenderInt64(field_name, absl::bit_cast<int64_t>(buffer64));
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderUInt64(
+absl::Status ProtoStreamObjectSource::RenderUInt64(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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();
+  ow->RenderUint64(field_name, absl::bit_cast<uint64_t>(buffer64));
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderInt32(
+absl::Status ProtoStreamObjectSource::RenderInt32(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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();
+  ow->RenderInt32(field_name, absl::bit_cast<int32_t>(buffer32));
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderUInt32(
+absl::Status ProtoStreamObjectSource::RenderUInt32(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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();
+  ow->RenderUint32(field_name, absl::bit_cast<uint32_t>(buffer32));
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderBool(
+absl::Status ProtoStreamObjectSource::RenderBool(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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
@@ -465,12 +474,12 @@
     os->stream_->ReadTag();
   }
   ow->RenderBool(field_name, buffer64 != 0);
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderString(
+absl::Status ProtoStreamObjectSource::RenderString(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view field_name, ObjectWriter* ow) {
   uint32_t tag = os->stream_->ReadTag();
   uint32_t buffer32;
   std::string str;  // default value of empty for String wrapper
@@ -480,12 +489,12 @@
     os->stream_->ReadTag();
   }
   ow->RenderString(field_name, str);
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderBytes(
+absl::Status ProtoStreamObjectSource::RenderBytes(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view field_name, ObjectWriter* ow) {
   uint32_t tag = os->stream_->ReadTag();
   uint32_t buffer32;
   std::string str;
@@ -495,12 +504,12 @@
     os->stream_->ReadTag();
   }
   ow->RenderBytes(field_name, str);
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderStruct(
+absl::Status ProtoStreamObjectSource::RenderStruct(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view field_name, ObjectWriter* ow) {
   const google::protobuf::Field* field = nullptr;
   uint32_t tag = os->stream_->ReadTag();
   ow->StartObject(field_name);
@@ -518,12 +527,12 @@
     }
   }
   ow->EndObject();
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderStructValue(
+absl::Status ProtoStreamObjectSource::RenderStructValue(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view field_name, ObjectWriter* ow) {
   const google::protobuf::Field* field = nullptr;
   for (uint32_t tag = os->stream_->ReadTag(); tag != 0;
        tag = os->stream_->ReadTag()) {
@@ -534,20 +543,20 @@
     }
     RETURN_IF_ERROR(os->RenderField(field, field_name, ow));
   }
-  return util::Status();
+  return absl::Status();
 }
 
 // TODO(skarvaje): Avoid code duplication of for loops and SkipField logic.
-util::Status ProtoStreamObjectSource::RenderStructListValue(
+absl::Status ProtoStreamObjectSource::RenderStructListValue(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view 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();
+    return absl::Status();
   }
 
   while (tag != 0) {
@@ -559,12 +568,12 @@
     }
     ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow));
   }
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderAny(
+absl::Status ProtoStreamObjectSource::RenderAny(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view field_name, ObjectWriter* ow) {
   // An Any is of the form { string type_url = 1; bytes value = 2; }
   uint32_t tag;
   std::string type_url;
@@ -600,22 +609,22 @@
       ow->RenderString("@type", type_url);
     }
     ow->EndObject();
-    return util::Status();
+    return absl::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.");
+    return absl::InternalError("Invalid Any, the type_url is missing.");
   }
 
-  util::StatusOr<const google::protobuf::Type*> resolved_type =
+  absl::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());
+    return absl::InternalError(resolved_type.status().message());
   }
   // nested_type cannot be null at this time.
   const google::protobuf::Type* nested_type = resolved_type.value();
@@ -630,15 +639,15 @@
   // 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 =
+  absl::Status result =
       nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow);
   ow->EndObject();
   return result;
 }
 
-util::Status ProtoStreamObjectSource::RenderFieldMask(
+absl::Status ProtoStreamObjectSource::RenderFieldMask(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
+    absl::string_view field_name, ObjectWriter* ow) {
   std::string combined;
   uint32_t buffer32;
   uint32_t paths_field_tag = 0;
@@ -652,7 +661,7 @@
       }
     }
     if (paths_field_tag != tag) {
-      return util::InternalError("Invalid FieldMask, unexpected field.");
+      return absl::InternalError("Invalid FieldMask, unexpected field.");
     }
     std::string str;
     os->stream_->ReadVarint32(&buffer32);  // string size.
@@ -663,13 +672,13 @@
     combined.append(ConvertFieldMaskPath(str, &ToCamelCase));
   }
   ow->RenderString(field_name, combined);
-  return util::Status();
+  return absl::Status();
 }
 
 
 std::unordered_map<std::string, ProtoStreamObjectSource::TypeRenderer>*
     ProtoStreamObjectSource::renderers_ = nullptr;
-PROTOBUF_NAMESPACE_ID::internal::once_flag source_renderers_init_;
+absl::once_flag source_renderers_init_;
 
 
 void ProtoStreamObjectSource::InitRendererMap() {
@@ -717,13 +726,14 @@
 // 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);
+  absl::call_once(source_renderers_init_, InitRendererMap);
+  auto it = renderers_->find(type_url);
+  if (it == renderers_->end()) return nullptr;
+  return &it->second;
 }
 
-util::Status ProtoStreamObjectSource::RenderField(
-    const google::protobuf::Field* field, StringPiece field_name,
+absl::Status ProtoStreamObjectSource::RenderField(
+    const google::protobuf::Field* field, absl::string_view 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
@@ -736,8 +746,8 @@
     const google::protobuf::Type* type =
         typeinfo_->GetTypeByTypeUrl(field->type_url());
     if (type == nullptr) {
-      return util::InternalError(
-          StrCat("Invalid configuration. Could not find the type: ",
+      return absl::InternalError(
+          absl::StrCat("Invalid configuration. Could not find the type: ",
                        field->type_url()));
     }
 
@@ -753,7 +763,7 @@
     --recursion_depth_;
 
     if (!stream_->ConsumedEntireMessage()) {
-      return util::InvalidArgumentError(
+      return absl::InvalidArgumentError(
           "Nested protocol message not parsed in its entirety.");
     }
     stream_->PopLimit(old_limit);
@@ -761,11 +771,11 @@
     // Render all other non-message types.
     return RenderNonMessageField(field, field_name, ow);
   }
-  return util::Status();
+  return absl::Status();
 }
 
-util::Status ProtoStreamObjectSource::RenderNonMessageField(
-    const google::protobuf::Field* field, StringPiece field_name,
+absl::Status ProtoStreamObjectSource::RenderNonMessageField(
+    const google::protobuf::Field* field, absl::string_view field_name,
     ObjectWriter* ow) const {
   // Temporary buffers of different types.
   uint32_t buffer32 = 0;
@@ -779,22 +789,22 @@
     }
     case google::protobuf::Field::TYPE_INT32: {
       stream_->ReadVarint32(&buffer32);
-      ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
+      ow->RenderInt32(field_name, absl::bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_INT64: {
       stream_->ReadVarint64(&buffer64);
-      ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64));
+      ow->RenderInt64(field_name, absl::bit_cast<int64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_UINT32: {
       stream_->ReadVarint32(&buffer32);
-      ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
+      ow->RenderUint32(field_name, absl::bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_UINT64: {
       stream_->ReadVarint64(&buffer64);
-      ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64));
+      ow->RenderUint64(field_name, absl::bit_cast<uint64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_SINT32: {
@@ -809,32 +819,32 @@
     }
     case google::protobuf::Field::TYPE_SFIXED32: {
       stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
+      ow->RenderInt32(field_name, absl::bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_SFIXED64: {
       stream_->ReadLittleEndian64(&buffer64);
-      ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64));
+      ow->RenderInt64(field_name, absl::bit_cast<int64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_FIXED32: {
       stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
+      ow->RenderUint32(field_name, absl::bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_FIXED64: {
       stream_->ReadLittleEndian64(&buffer64);
-      ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64));
+      ow->RenderUint64(field_name, absl::bit_cast<uint64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_FLOAT: {
       stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderFloat(field_name, bit_cast<float>(buffer32));
+      ow->RenderFloat(field_name, absl::bit_cast<float>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_DOUBLE: {
       stream_->ReadLittleEndian64(&buffer64);
-      ow->RenderDouble(field_name, bit_cast<double>(buffer64));
+      ow->RenderDouble(field_name, absl::bit_cast<double>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_ENUM: {
@@ -888,11 +898,11 @@
     default:
       break;
   }
-  return util::Status();
+  return absl::Status();
 }
 
 // TODO(skarvaje): Fix this to avoid code duplication.
-const std::string ProtoStreamObjectSource::ReadFieldValueAsString(
+std::string ProtoStreamObjectSource::ReadFieldValueAsString(
     const google::protobuf::Field& field) const {
   std::string result;
   switch (field.kind()) {
@@ -905,73 +915,73 @@
     case google::protobuf::Field::TYPE_INT32: {
       uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
-      result = StrCat(bit_cast<int32_t>(buffer32));
+      result = absl::StrCat(absl::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));
+      result = absl::StrCat(absl::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));
+      result = absl::StrCat(absl::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));
+      result = absl::StrCat(absl::bit_cast<uint64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_SINT32: {
       uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
-      result = StrCat(WireFormatLite::ZigZagDecode32(buffer32));
+      result = absl::StrCat(WireFormatLite::ZigZagDecode32(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_SINT64: {
       uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
-      result = StrCat(WireFormatLite::ZigZagDecode64(buffer64));
+      result = absl::StrCat(WireFormatLite::ZigZagDecode64(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_SFIXED32: {
       uint32_t buffer32;
       stream_->ReadLittleEndian32(&buffer32);
-      result = StrCat(bit_cast<int32_t>(buffer32));
+      result = absl::StrCat(absl::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));
+      result = absl::StrCat(absl::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));
+      result = absl::StrCat(absl::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));
+      result = absl::StrCat(absl::bit_cast<uint64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_FLOAT: {
       uint32_t buffer32;
       stream_->ReadLittleEndian32(&buffer32);
-      result = SimpleFtoa(bit_cast<float>(buffer32));
+      result = SimpleFtoa(absl::bit_cast<float>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_DOUBLE: {
       uint64_t buffer64;
       stream_->ReadLittleEndian64(&buffer64);
-      result = SimpleDtoa(bit_cast<double>(buffer64));
+      result = SimpleDtoa(absl::bit_cast<double>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_ENUM: {
@@ -1039,24 +1049,24 @@
     if (field->number() == 1) {
       // read seconds
       stream_->ReadVarint64(&seconds);
-      signed_seconds = bit_cast<int64_t>(seconds);
+      signed_seconds = absl::bit_cast<int64_t>(seconds);
     } else if (field->number() == 2) {
       // read nanos
       stream_->ReadVarint32(&nanos);
-      signed_nanos = bit_cast<int32_t>(nanos);
+      signed_nanos = absl::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 {
+absl::Status ProtoStreamObjectSource::IncrementRecursionDepth(
+    absl::string_view type_name, absl::string_view field_name) const {
   if (++recursion_depth_ > max_recursion_depth_) {
-    return util::InvalidArgumentError(
-        StrCat("Message too deep. Max recursion depth reached for type '",
+    return absl::InvalidArgumentError(
+        absl::StrCat("Message too deep. Max recursion depth reached for type '",
                      type_name, "', field '", field_name, "'"));
   }
-  return util::Status();
+  return absl::Status();
 }
 
 namespace {
@@ -1093,7 +1103,7 @@
 
 // TODO(skarvaje): Look into optimizing this by not doing computation on
 // double.
-const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros) {
+std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros) {
   if (nanos == 0) {
     return with_trailing_zeros ? ".000" : "";
   }
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 8ed2ca9..350966b 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -36,22 +36,21 @@
 #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>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/type.pb.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.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"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -77,9 +76,6 @@
  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.
     //
@@ -123,10 +119,12 @@
                           TypeResolver* type_resolver,
                           const google::protobuf::Type& type,
                           const RenderOptions& render_options);
-
+  ProtoStreamObjectSource() = delete;
+  ProtoStreamObjectSource(const ProtoStreamObjectSource&) = delete;
+  ProtoStreamObjectSource& operator=(const ProtoStreamObjectSource&) = delete;
   ~ProtoStreamObjectSource() override;
 
-  util::Status NamedWriteTo(StringPiece name,
+  absl::Status NamedWriteTo(absl::string_view name,
                             ObjectWriter* ow) const override;
 
   // Sets the max recursion depth of proto message to be deserialized. Proto
@@ -142,8 +140,8 @@
   // 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,
+  virtual absl::Status WriteMessage(const google::protobuf::Type& type,
+                                    absl::string_view name,
                                     const uint32_t end_tag,
                                     bool include_start_and_end,
                                     ObjectWriter* ow) const;
@@ -151,8 +149,8 @@
   // 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,
+  virtual absl::StatusOr<uint32_t> RenderList(
+      const google::protobuf::Field* field, absl::string_view name,
       uint32_t list_tag, ObjectWriter* ow) const;
 
   // Looks up a field and verify its consistency with wire type in tag.
@@ -160,14 +158,14 @@
       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,
+  virtual absl::Status RenderField(const google::protobuf::Field* field,
+                                   absl::string_view 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(
+  std::string ReadFieldValueAsString(
       const google::protobuf::Field& field) const;
 
 
@@ -180,9 +178,9 @@
                           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*,
+  typedef absl::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
                                        const google::protobuf::Type&,
-                                       StringPiece, ObjectWriter*);
+                                       absl::string_view, ObjectWriter*);
 
   // TODO(skarvaje): Mark these methods as non-const as they modify internal
   // state (stream_).
@@ -190,82 +188,82 @@
   // 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,
+  absl::StatusOr<uint32_t> RenderMap(const google::protobuf::Field* field,
+                                     absl::string_view 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,
+  absl::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,
+  static absl::Status RenderTimestamp(const ProtoStreamObjectSource* os,
                                       const google::protobuf::Type& type,
-                                      StringPiece name, ObjectWriter* ow);
+                                      absl::string_view name, ObjectWriter* ow);
 
   // Renders a google.protobuf.Duration value to ObjectWriter
-  static util::Status RenderDuration(const ProtoStreamObjectSource* os,
+  static absl::Status RenderDuration(const ProtoStreamObjectSource* os,
                                      const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
+                                     absl::string_view 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,
+  static absl::Status RenderDouble(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
-                                   StringPiece name, ObjectWriter* ow);
-  static util::Status RenderFloat(const ProtoStreamObjectSource* os,
+                                   absl::string_view name, ObjectWriter* ow);
+  static absl::Status RenderFloat(const ProtoStreamObjectSource* os,
                                   const google::protobuf::Type& type,
-                                  StringPiece name, ObjectWriter* ow);
-  static util::Status RenderInt64(const ProtoStreamObjectSource* os,
+                                  absl::string_view name, ObjectWriter* ow);
+  static absl::Status RenderInt64(const ProtoStreamObjectSource* os,
                                   const google::protobuf::Type& type,
-                                  StringPiece name, ObjectWriter* ow);
-  static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
+                                  absl::string_view name, ObjectWriter* ow);
+  static absl::Status RenderUInt64(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
-                                   StringPiece name, ObjectWriter* ow);
-  static util::Status RenderInt32(const ProtoStreamObjectSource* os,
+                                   absl::string_view name, ObjectWriter* ow);
+  static absl::Status RenderInt32(const ProtoStreamObjectSource* os,
                                   const google::protobuf::Type& type,
-                                  StringPiece name, ObjectWriter* ow);
-  static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
+                                  absl::string_view name, ObjectWriter* ow);
+  static absl::Status RenderUInt32(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
-                                   StringPiece name, ObjectWriter* ow);
-  static util::Status RenderBool(const ProtoStreamObjectSource* os,
+                                   absl::string_view name, ObjectWriter* ow);
+  static absl::Status RenderBool(const ProtoStreamObjectSource* os,
                                  const google::protobuf::Type& type,
-                                 StringPiece name, ObjectWriter* ow);
-  static util::Status RenderString(const ProtoStreamObjectSource* os,
+                                 absl::string_view name, ObjectWriter* ow);
+  static absl::Status RenderString(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
-                                   StringPiece name, ObjectWriter* ow);
-  static util::Status RenderBytes(const ProtoStreamObjectSource* os,
+                                   absl::string_view name, ObjectWriter* ow);
+  static absl::Status RenderBytes(const ProtoStreamObjectSource* os,
                                   const google::protobuf::Type& type,
-                                  StringPiece name, ObjectWriter* ow);
+                                  absl::string_view name, ObjectWriter* ow);
 
   // Renders a google.protobuf.Struct to ObjectWriter.
-  static util::Status RenderStruct(const ProtoStreamObjectSource* os,
+  static absl::Status RenderStruct(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
-                                   StringPiece name, ObjectWriter* ow);
+                                   absl::string_view name, ObjectWriter* ow);
 
   // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
-  static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
+  static absl::Status RenderStructValue(const ProtoStreamObjectSource* os,
                                         const google::protobuf::Type& type,
-                                        StringPiece name,
+                                        absl::string_view name,
                                         ObjectWriter* ow);
 
   // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
-  static util::Status RenderStructListValue(const ProtoStreamObjectSource* os,
+  static absl::Status RenderStructListValue(const ProtoStreamObjectSource* os,
                                             const google::protobuf::Type& type,
-                                            StringPiece name,
+                                            absl::string_view name,
                                             ObjectWriter* ow);
 
   // Render the "Any" type.
-  static util::Status RenderAny(const ProtoStreamObjectSource* os,
+  static absl::Status RenderAny(const ProtoStreamObjectSource* os,
                                 const google::protobuf::Type& type,
-                                StringPiece name, ObjectWriter* ow);
+                                absl::string_view name, ObjectWriter* ow);
 
   // Render the "FieldMask" type.
-  static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
+  static absl::Status RenderFieldMask(const ProtoStreamObjectSource* os,
                                       const google::protobuf::Type& type,
-                                      StringPiece name, ObjectWriter* ow);
+                                      absl::string_view name, ObjectWriter* ow);
 
   static std::unordered_map<std::string, TypeRenderer>* renderers_;
   static void InitRendererMap();
@@ -274,8 +272,8 @@
 
   // Same as above but renders all non-message field types. Callers don't call
   // this function directly. They just use RenderField.
-  util::Status RenderNonMessageField(const google::protobuf::Field* field,
-                                     StringPiece field_name,
+  absl::Status RenderNonMessageField(const google::protobuf::Field* field,
+                                     absl::string_view field_name,
                                      ObjectWriter* ow) const;
 
 
@@ -290,8 +288,8 @@
   // 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;
+  absl::Status IncrementRecursionDepth(absl::string_view type_name,
+                                       absl::string_view field_name) const;
 
   // Input stream to read from. Ownership rests with the caller.
   mutable io::CodedInputStream* stream_;
@@ -315,8 +313,6 @@
 
   // Maximum allowed recursion depth.
   int max_recursion_depth_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
 };
 
 }  // namespace converter
@@ -324,6 +320,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index e16db78..4fde30b 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -28,29 +28,30 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <google/protobuf/util/internal/protostream_objectsource.h>
+#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 "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 <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>
+#include "absl/base/casts.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/util/internal/constants.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 "google/protobuf/util/internal/type_info_test_helper.h"
 
 
 namespace google {
@@ -106,11 +107,11 @@
   ~ProtostreamObjectSourceTest() override {}
 
   void DoTest(const Message& msg, const Descriptor* descriptor) {
-    util::Status status = ExecuteTest(msg, descriptor);
-    EXPECT_EQ(util::Status(), status);
+    absl::Status status = ExecuteTest(msg, descriptor);
+    EXPECT_EQ(absl::Status(), status);
   }
 
-  util::Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
+  absl::Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
     std::ostringstream oss;
     msg.SerializePartialToOstream(&oss);
     std::string proto = oss.str();
@@ -130,13 +131,13 @@
   void PrepareExpectingObjectWriterForRepeatedPrimitive() {
     ow_.StartObject("")
         ->StartList("repFix32")
-        ->RenderUint32("", bit_cast<uint32_t>(3201))
-        ->RenderUint32("", bit_cast<uint32_t>(0))
-        ->RenderUint32("", bit_cast<uint32_t>(3202))
+        ->RenderUint32("", absl::bit_cast<uint32_t>(3201))
+        ->RenderUint32("", absl::bit_cast<uint32_t>(0))
+        ->RenderUint32("", absl::bit_cast<uint32_t>(3202))
         ->EndList()
         ->StartList("repU32")
-        ->RenderUint32("", bit_cast<uint32_t>(3203))
-        ->RenderUint32("", bit_cast<uint32_t>(0))
+        ->RenderUint32("", absl::bit_cast<uint32_t>(3203))
+        ->RenderUint32("", absl::bit_cast<uint32_t>(0))
         ->EndList()
         ->StartList("repI32")
         ->RenderInt32("", 0)
@@ -153,13 +154,13 @@
         ->RenderInt32("", 3208)
         ->EndList()
         ->StartList("repFix64")
-        ->RenderUint64("", bit_cast<uint64_t>(int64_t{6401}))
-        ->RenderUint64("", bit_cast<uint64_t>(int64_t{0}))
+        ->RenderUint64("", absl::bit_cast<uint64_t>(int64_t{6401}))
+        ->RenderUint64("", absl::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}))
+        ->RenderUint64("", absl::bit_cast<uint64_t>(int64_t{0}))
+        ->RenderUint64("", absl::bit_cast<uint64_t>(int64_t{6402}))
+        ->RenderUint64("", absl::bit_cast<uint64_t>(int64_t{6403}))
         ->EndList()
         ->StartList("repI64")
         ->RenderInt64("", 6404L)
@@ -321,13 +322,13 @@
   primitive.set_bool_(true);
 
   ow_.StartObject("")
-      ->RenderUint32("fix32", bit_cast<uint32_t>(3201))
-      ->RenderUint32("u32", bit_cast<uint32_t>(3202))
+      ->RenderUint32("fix32", absl::bit_cast<uint32_t>(3201))
+      ->RenderUint32("u32", absl::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}))
+      ->RenderUint64("fix64", absl::bit_cast<uint64_t>(int64_t{6401}))
+      ->RenderUint64("u64", absl::bit_cast<uint64_t>(int64_t{6402}))
       ->RenderInt64("i64", 6403L)
       ->RenderInt64("sf64", 6404L)
       ->RenderInt64("s64", 6405L)
@@ -478,8 +479,8 @@
   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));
+    label->set_key(absl::StrCat("i", i));
+    label->set_value(absl::StrCat("v", i));
   }
 
   // Make sure StartList and EndList are called exactly once (see b/18227499 for
@@ -584,7 +585,7 @@
   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_name(absl::StrCat("author_name_", i));
     next->set_alive(true);
     current_author = next;
   }
@@ -592,12 +593,12 @@
   // 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));
+    next->set_m_str(absl::StrCat("count_", i));
     current = next;
   }
 
-  util::Status status = ExecuteTest(cyclic, Cyclic::descriptor());
-  EXPECT_TRUE(util::IsInvalidArgument(status));
+  absl::Status status = ExecuteTest(cyclic, Cyclic::descriptor());
+  EXPECT_TRUE(absl::IsInvalidArgument(status));
 }
 
 class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
@@ -942,8 +943,8 @@
   // 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));
+  absl::Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_TRUE(absl::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
@@ -958,8 +959,8 @@
   // 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));
+  absl::Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_TRUE(absl::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
@@ -974,8 +975,8 @@
   // 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));
+  absl::Status status = ExecuteTest(out, AnyOut::descriptor());
+  EXPECT_TRUE(absl::IsInternal(status));
 }
 
 class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
@@ -1107,8 +1108,8 @@
   ts->set_seconds(kTimestampMinSeconds - 1);
   ow_.StartObject("");
 
-  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
+  absl::Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_TRUE(absl::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
@@ -1118,8 +1119,8 @@
   ts->set_seconds(kTimestampMaxSeconds + 1);
   ow_.StartObject("");
 
-  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
+  absl::Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_TRUE(absl::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
@@ -1129,8 +1130,8 @@
   dur->set_seconds(kDurationMinSeconds - 1);
   ow_.StartObject("");
 
-  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
+  absl::Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_TRUE(absl::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
@@ -1140,8 +1141,8 @@
   dur->set_seconds(kDurationMaxSeconds + 1);
   ow_.StartObject("");
 
-  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
+  absl::Status status = ExecuteTest(out, TimestampDuration::descriptor());
+  EXPECT_TRUE(absl::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, TimestampDurationDefaultValue) {
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index ecb219e..677647e 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.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/internal/protostream_objectwriter.h>
+#include "google/protobuf/util/internal/protostream_objectwriter.h"
 
 #include <cstdint>
 #include <functional>
@@ -36,28 +36,29 @@
 #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>
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/stubs/strutil.h"
+#include "absl/base/call_once.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/strip.h"
+#include "absl/time/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"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace util {
 namespace converter {
 
-using util::Status;
+using ::absl::Status;
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
 using std::placeholders::_1;
 
@@ -115,19 +116,19 @@
 namespace {
 // Utility method to split a string representation of Timestamp or Duration and
 // return the parts.
-void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds,
-                          StringPiece* nanos) {
+void SplitSecondsAndNanos(absl::string_view input, absl::string_view* seconds,
+                          absl::string_view* 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();
+    *nanos = absl::string_view();
   }
 }
 
-Status GetNanosFromStringPiece(StringPiece s_nanos,
+Status GetNanosFromStringPiece(absl::string_view s_nanos,
                                const char* parse_failure_message,
                                const char* exceeded_limit_message,
                                int32_t* nanos) {
@@ -135,7 +136,7 @@
 
   // Count the number of leading 0s and consume them.
   int num_leading_zeros = 0;
-  while (s_nanos.Consume("0")) {
+  while (absl::ConsumePrefix(&s_nanos, "0")) {
     num_leading_zeros++;
   }
   int32_t i_nanos = 0;
@@ -144,14 +145,14 @@
   // 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);
+    return absl::InvalidArgumentError(parse_failure_message);
   }
   if (i_nanos > kNanosPerSecond || i_nanos < 0) {
-    return util::InvalidArgumentError(exceeded_limit_message);
+    return absl::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 (s_nanos.find_first_not_of("0123456789") != absl::string_view::npos) {
+    return absl::InvalidArgumentError(parse_failure_message);
   }
 
   if (i_nanos > 0) {
@@ -191,7 +192,7 @@
         conversion = 1;
         break;
       default:
-        return util::InvalidArgumentError(exceeded_limit_message);
+        return absl::InvalidArgumentError(exceeded_limit_message);
     }
     *nanos = i_nanos * conversion;
   }
@@ -199,6 +200,26 @@
   return Status();
 }
 
+// If successful, stores the offset in seconds in "value" and returns true.
+// Caller must ensure the first character of "offset" is "+" or "-".
+bool ParseTimezoneOffset(absl::string_view offset, int* value) {
+  GOOGLE_DCHECK(offset[0] == '+' || offset[0] == '-');
+  // Format of the offset: +DD:DD or -DD:DD. E.g., +08:00.
+  if (offset.length() != 6 || offset[3] != ':') {
+    return false;
+  }
+  int hours = 0, minutes = 0;
+  if (!safe_strto32(offset.substr(1, 2), &hours) ||
+      !safe_strto32(offset.substr(4, 2), &minutes) || hours < 0 ||
+      hours >= 24 || minutes < 0 || minutes >= 60) {
+    return false;
+  }
+  *value = (hours * 60 + minutes) * 60;
+  if (offset[0] == '-') {
+    *value = -*value;
+  }
+  return true;
+}
 }  // namespace
 
 ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent)
@@ -213,7 +234,7 @@
 
 ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {}
 
-void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) {
+void ProtoStreamObjectWriter::AnyWriter::StartObject(absl::string_view 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"
@@ -260,7 +281,7 @@
   return true;
 }
 
-void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) {
+void ProtoStreamObjectWriter::AnyWriter::StartList(absl::string_view name) {
   ++depth_;
   if (ow_ == nullptr) {
     // Save data before the "@type" field for later replay.
@@ -292,7 +313,7 @@
 }
 
 void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece(
-    StringPiece name, const DataPiece& value) {
+    absl::string_view 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") {
@@ -330,7 +351,7 @@
   if (value.type() == DataPiece::TYPE_STRING) {
     type_url_ = std::string(value.str());
   } else {
-    util::StatusOr<std::string> s = value.ToString();
+    absl::StatusOr<std::string> s = value.ToString();
     if (!s.ok()) {
       parent_->InvalidValue("String", s.status().message());
       invalid_ = true;
@@ -339,7 +360,7 @@
     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 =
+  absl::StatusOr<const google::protobuf::Type*> resolved_type =
       parent_->typeinfo()->ResolveTypeUrl(type_url_);
   if (!resolved_type.ok()) {
     parent_->InvalidValue("Any", resolved_type.status().message());
@@ -393,7 +414,7 @@
       // There are uninterpreted data, but we never got a "@type" field.
       if (!invalid_) {
         parent_->InvalidValue("Any",
-                              StrCat("Missing @type for any field in ",
+                              absl::StrCat("Missing @type for any field in ",
                                            parent_->master_type_.name()));
         invalid_ = true;
       }
@@ -434,7 +455,7 @@
   // 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());
+    absl::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();
@@ -455,9 +476,6 @@
   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,
@@ -472,19 +490,16 @@
   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));
+    absl::string_view map_key) {
+  return map_keys_.insert(std::string(map_key)).second;
 }
 
 
 ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
-    StringPiece name) {
+    absl::string_view name) {
   if (invalid_depth() > 0) {
     IncrementInvalidDepth();
     return this;
@@ -680,7 +695,7 @@
 
 
 ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(
-    StringPiece name) {
+    absl::string_view name) {
   if (invalid_depth() > 0) {
     IncrementInvalidDepth();
     return this;
@@ -788,7 +803,7 @@
     }
 
     // Report an error.
-    InvalidValue("Map", StrCat("Cannot have repeated items ('", name,
+    InvalidValue("Map", absl::StrCat("Cannot have repeated items ('", name,
                                      "') within a map."));
     return this;
   }
@@ -885,7 +900,7 @@
       Push(name, Item::MESSAGE, false, true);
       return this;
     }
-    InvalidValue("Map", StrCat("Cannot bind a list to map for field '",
+    InvalidValue("Map", absl::StrCat("Cannot bind a list to map for field '",
                                      name, "'."));
     IncrementInvalidDepth();
     return this;
@@ -921,7 +936,7 @@
   switch (data.type()) {
     case DataPiece::TYPE_INT32: {
       if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<int32_t> int_value = data.ToInt32();
+        absl::StatusOr<int32_t> int_value = data.ToInt32();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -934,7 +949,7 @@
     }
     case DataPiece::TYPE_UINT32: {
       if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<uint32_t> int_value = data.ToUint32();
+        absl::StatusOr<uint32_t> int_value = data.ToUint32();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -949,10 +964,10 @@
       // 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();
+        absl::StatusOr<int64_t> int_value = data.ToInt64();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
-              "string_value", DataPiece(StrCat(int_value.value()), true));
+              "string_value", DataPiece(absl::StrCat(int_value.value()), true));
           return Status();
         }
       }
@@ -963,10 +978,10 @@
       // 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();
+        absl::StatusOr<uint64_t> int_value = data.ToUint64();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
-              "string_value", DataPiece(StrCat(int_value.value()), true));
+              "string_value", DataPiece(absl::StrCat(int_value.value()), true));
           return Status();
         }
       }
@@ -975,7 +990,7 @@
     }
     case DataPiece::TYPE_FLOAT: {
       if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<float> float_value = data.ToFloat();
+        absl::StatusOr<float> float_value = data.ToFloat();
         if (float_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -988,7 +1003,7 @@
     }
     case DataPiece::TYPE_DOUBLE: {
       if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<double> double_value = data.ToDouble();
+        absl::StatusOr<double> double_value = data.ToDouble();
         if (double_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -1012,7 +1027,7 @@
       break;
     }
     default: {
-      return util::InvalidArgumentError(
+      return absl::InvalidArgumentError(
           "Invalid struct data type. Only number, string, boolean or  null "
           "values are supported.");
     }
@@ -1025,28 +1040,57 @@
                                                 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 ",
+    return absl::InvalidArgumentError(
+        absl::StrCat("Invalid data type for timestamp, value is ",
                      data.ValueAsStringOrDefault("")));
   }
 
-  StringPiece value(data.str());
+  absl::string_view 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));
+  int timezone_offset_seconds = 0;
+  if (HasSuffixString(value, "Z")) {
+    value = value.substr(0, value.size() - 1);
+  } else {
+    size_t pos = value.find_last_of("+-");
+    if (pos == std::string::npos ||
+        !ParseTimezoneOffset(value.substr(pos), &timezone_offset_seconds)) {
+      return Status(absl::StatusCode::kInvalidArgument,
+                    "Illegal timestamp format; timestamps must end with 'Z' "
+                    "or have a valid timezone offset.");
+    }
+    value = value.substr(0, pos);
   }
 
+  absl::string_view s_secs, s_nanos;
+  SplitSecondsAndNanos(value, &s_secs, &s_nanos);
+  absl::Time tm;
+  std::string err;
+  if (!absl::ParseTime(kRfc3339TimeFormatNoPadding, s_secs, &tm, &err)) {
+    return Status(absl::StatusCode::kInvalidArgument,
+                  absl::StrCat("Invalid time format: ", err));
+  }
+
+  int32_t nanos = 0;
+  Status nanos_status = GetNanosFromStringPiece(
+      s_nanos, "Invalid time format, failed to parse nano seconds",
+      "Timestamp value exceeds limits", &nanos);
+  if (!nanos_status.ok()) {
+    return nanos_status;
+  }
+
+  int64_t seconds = absl::ToUnixSeconds(tm) - timezone_offset_seconds;
+  if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) {
+    return Status(absl::StatusCode::kInvalidArgument,
+                  "Timestamp value exceeds limits");
+  }
 
   ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
   ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos));
   return Status();
 }
 
-static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
-                                              StringPiece path) {
+static inline absl::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
+                                              absl::string_view path) {
   ow->ProtoWriter::RenderDataPiece(
       "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true));
   return Status();
@@ -1056,8 +1100,8 @@
                                                 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 ",
+    return absl::InvalidArgumentError(
+        absl::StrCat("Invalid data type for field mask, value is ",
                      data.ValueAsStringOrDefault("")));
   }
 
@@ -1072,15 +1116,15 @@
                                                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 ",
+    return absl::InvalidArgumentError(
+        absl::StrCat("Invalid data type for duration, value is ",
                      data.ValueAsStringOrDefault("")));
   }
 
-  StringPiece value(data.str());
+  absl::string_view value(data.str());
 
   if (!HasSuffixString(value, "s")) {
-    return util::InvalidArgumentError(
+    return absl::InvalidArgumentError(
         "Illegal duration format; duration must end with 's'");
   }
   value = value.substr(0, value.size() - 1);
@@ -1090,11 +1134,11 @@
     value = value.substr(1);
   }
 
-  StringPiece s_secs, s_nanos;
+  absl::string_view s_secs, s_nanos;
   SplitSecondsAndNanos(value, &s_secs, &s_nanos);
   uint64_t unsigned_seconds;
   if (!safe_strtou64(s_secs, &unsigned_seconds)) {
-    return util::InvalidArgumentError(
+    return absl::InvalidArgumentError(
         "Invalid duration format, failed to parse seconds");
   }
 
@@ -1110,7 +1154,7 @@
   int64_t seconds = sign * unsigned_seconds;
   if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds ||
       nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
-    return util::InvalidArgumentError("Duration value exceeds limits");
+    return absl::InvalidArgumentError("Duration value exceeds limits");
   }
 
   ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
@@ -1126,7 +1170,7 @@
 }
 
 ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
-    StringPiece name, const DataPiece& data) {
+    absl::string_view name, const DataPiece& data) {
   Status status;
   if (invalid_depth() > 0) return this;
 
@@ -1145,7 +1189,7 @@
     status = (*type_renderer)(this, data);
     if (!status.ok()) {
       InvalidValue(master_type_.name(),
-                   StrCat("Field '", name, "', ", status.message()));
+                   absl::StrCat("Field '", name, "', ", status.message()));
     }
     ProtoWriter::EndObject();
     return this;
@@ -1191,7 +1235,7 @@
       status = (*type_renderer)(this, data);
       if (!status.ok()) {
         InvalidValue(field->type_url(),
-                     StrCat("Field '", name, "', ", status.message()));
+                     absl::StrCat("Field '", name, "', ", status.message()));
       }
       Pop();
       return this;
@@ -1225,7 +1269,7 @@
       status = (*type_renderer)(this, data);
       if (!status.ok()) {
         InvalidValue(field->type_url(),
-                     StrCat("Field '", name, "', ", status.message()));
+                     absl::StrCat("Field '", name, "', ", status.message()));
       }
       Pop();
     }
@@ -1260,7 +1304,7 @@
 // represented by the key.
 std::unordered_map<std::string, ProtoStreamObjectWriter::TypeRenderer>*
     ProtoStreamObjectWriter::renderers_ = nullptr;
-PROTOBUF_NAMESPACE_ID::internal::once_flag writer_renderers_init_;
+absl::once_flag writer_renderers_init_;
 
 void ProtoStreamObjectWriter::InitRendererMap() {
   renderers_ = new std::unordered_map<std::string,
@@ -1319,18 +1363,19 @@
 
 ProtoStreamObjectWriter::TypeRenderer*
 ProtoStreamObjectWriter::FindTypeRenderer(const std::string& type_url) {
-  PROTOBUF_NAMESPACE_ID::internal::call_once(writer_renderers_init_,
-                                             InitRendererMap);
-  return FindOrNull(*renderers_, type_url);
+  absl::call_once(writer_renderers_init_, InitRendererMap);
+  auto it = renderers_->find(type_url);
+  if (it == renderers_->end()) return nullptr;
+  return &it->second;
 }
 
-bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) {
+bool ProtoStreamObjectWriter::ValidMapKey(absl::string_view unnormalized_name) {
   if (current_ == nullptr) return true;
 
   if (!current_->InsertMapKeyIfNotPresent(unnormalized_name)) {
     listener()->InvalidName(
         location(), unnormalized_name,
-        StrCat("Repeated map key: '", unnormalized_name,
+        absl::StrCat("Repeated map key: '", unnormalized_name,
                      "' is already set."));
     return false;
   }
@@ -1339,7 +1384,7 @@
 }
 
 void ProtoStreamObjectWriter::Push(
-    StringPiece name, Item::ItemType item_type, bool is_placeholder,
+    absl::string_view name, Item::ItemType item_type, bool is_placeholder,
     bool is_list) {
   is_list ? ProtoWriter::StartList(name) : ProtoWriter::StartObject(name);
 
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index ce2517f..95fedf8 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -36,23 +36,25 @@
 #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>
+#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 "absl/container/flat_hash_set.h"
+#include "absl/status/status.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.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"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -151,22 +153,25 @@
                           strings::ByteSink* output, ErrorListener* listener,
                           const ProtoStreamObjectWriter::Options& options =
                               ProtoStreamObjectWriter::Options::Defaults());
+  ProtoStreamObjectWriter() = delete;
+  ProtoStreamObjectWriter(const ProtoStreamObjectWriter&) = delete;
+  ProtoStreamObjectWriter& operator=(const ProtoStreamObjectWriter&) = delete;
   ~ProtoStreamObjectWriter() override;
 
   // ObjectWriter methods.
-  ProtoStreamObjectWriter* StartObject(StringPiece name) override;
+  ProtoStreamObjectWriter* StartObject(absl::string_view name) override;
   ProtoStreamObjectWriter* EndObject() override;
-  ProtoStreamObjectWriter* StartList(StringPiece name) override;
+  ProtoStreamObjectWriter* StartList(absl::string_view 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,
+  ProtoStreamObjectWriter* RenderDataPiece(absl::string_view name,
                                            const DataPiece& data) override;
 
  protected:
   // Function that renders a well known type with modified behavior.
-  typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
+  typedef absl::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
                                        const DataPiece&);
 
   // Handles writing Anys out using nested object writers and the like.
@@ -176,7 +181,7 @@
     ~AnyWriter();
 
     // Passes a StartObject call through to the Any writer.
-    void StartObject(StringPiece name);
+    void StartObject(absl::string_view 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
@@ -184,13 +189,13 @@
     bool EndObject();
 
     // Passes a StartList call through to the Any writer.
-    void StartList(StringPiece name);
+    void StartList(absl::string_view 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);
+    void RenderDataPiece(absl::string_view name, const DataPiece& value);
 
    private:
     // Before the "@type" field is encountered, we store all incoming data
@@ -209,11 +214,11 @@
       explicit Event(Type type) : type_(type), value_(DataPiece::NullData()) {}
 
       // Constructor for START_OBJECT and START_LIST events.
-      explicit Event(Type type, StringPiece name)
+      explicit Event(Type type, absl::string_view name)
           : type_(type), name_(name), value_(DataPiece::NullData()) {}
 
       // Constructor for RENDER_DATA_PIECE events.
-      explicit Event(StringPiece name, const DataPiece& value)
+      explicit Event(absl::string_view name, const DataPiece& value)
           : type_(RENDER_DATA_PIECE), name_(name), value_(value) {
         DeepCopy();
       }
@@ -299,6 +304,9 @@
 
     // Constructor for a field of a message.
     Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list);
+    Item() = delete;
+    Item(const Item&) = delete;
+    Item& operator=(const Item&) = delete;
 
     ~Item() override {}
 
@@ -318,7 +326,7 @@
     // 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 InsertMapKeyIfNotPresent(absl::string_view map_key);
 
     bool is_placeholder() const { return is_placeholder_; }
     bool is_list() const { return is_list_; }
@@ -336,7 +344,7 @@
 
     // 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_;
+    absl::flat_hash_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.
@@ -345,8 +353,6 @@
     // 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,
@@ -375,24 +381,24 @@
 
   // Renders google.protobuf.Value in struct.proto. It picks the right oneof
   // type based on value's type.
-  static util::Status RenderStructValue(ProtoStreamObjectWriter* ow,
+  static absl::Status RenderStructValue(ProtoStreamObjectWriter* ow,
                                         const DataPiece& data);
 
   // Renders google.protobuf.Timestamp value.
-  static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
+  static absl::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
                                       const DataPiece& data);
 
   // Renders google.protobuf.FieldMask value.
-  static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
+  static absl::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
                                       const DataPiece& data);
 
   // Renders google.protobuf.Duration value.
-  static util::Status RenderDuration(ProtoStreamObjectWriter* ow,
+  static absl::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,
+  static absl::Status RenderWrapperType(ProtoStreamObjectWriter* ow,
                                         const DataPiece& data);
 
   static void InitRendererMap();
@@ -405,7 +411,7 @@
   // 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);
+  bool ValidMapKey(absl::string_view 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
@@ -413,7 +419,7 @@
   // 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,
+  void Push(absl::string_view name, Item::ItemType item_type,
             bool is_placeholder, bool is_list);
 
 
@@ -439,8 +445,6 @@
 
   // Reference to the options that control this class's behavior.
   const ProtoStreamObjectWriter::Options options_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter);
 };
 
 }  // namespace converter
@@ -448,6 +452,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 3348999..640085f 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -28,36 +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/util/internal/protostream_objectwriter.h>
+#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 "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/stubs/bytestream.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>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/util/internal/constants.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/util/internal/type_info_test_helper.h"
+#include "google/protobuf/util/message_differencer.h"
+#include "google/protobuf/util/type_resolver_util.h"
 
 
 namespace google {
@@ -543,17 +543,17 @@
 
   ResetTypeInfo(Primitive::descriptor());
 
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
-                                      StringPiece("\"Infinity\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_INT32"),
+                                      absl::string_view("\"Infinity\"")))
       .With(Args<0>(HasObjectLocation("i32")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
-                                      StringPiece("\"Infinity\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_UINT32"),
+                                      absl::string_view("\"Infinity\"")))
       .With(Args<0>(HasObjectLocation("u32")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
-                                      StringPiece("\"-Infinity\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_SFIXED64"),
+                                      absl::string_view("\"-Infinity\"")))
       .With(Args<0>(HasObjectLocation("sf64")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"),
-                                      StringPiece("\"Infinity\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_BOOL"),
+                                      absl::string_view("\"Infinity\"")))
       .With(Args<0>(HasObjectLocation("bool")));
 
   ow_->StartObject("")
@@ -576,17 +576,17 @@
 
   ResetTypeInfo(Primitive::descriptor());
 
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
-                                      StringPiece("\"NaN\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_INT32"),
+                                      absl::string_view("\"NaN\"")))
       .With(Args<0>(HasObjectLocation("i32")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
-                                      StringPiece("\"NaN\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_UINT32"),
+                                      absl::string_view("\"NaN\"")))
       .With(Args<0>(HasObjectLocation("u32")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
-                                      StringPiece("\"NaN\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_SFIXED64"),
+                                      absl::string_view("\"NaN\"")))
       .With(Args<0>(HasObjectLocation("sf64")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"),
-                                      StringPiece("\"NaN\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_BOOL"),
+                                      absl::string_view("\"NaN\"")))
       .With(Args<0>(HasObjectLocation("bool")));
 
   ow_->StartObject("")
@@ -659,8 +659,8 @@
 
   EXPECT_CALL(
       listener_,
-      InvalidName(_, StringPiece("name"),
-                  StringPiece(
+      InvalidName(_, absl::string_view("name"),
+                  absl::string_view(
                       "Proto field is not repeating, cannot start list.")))
       .With(Args<0>(HasObjectLocation("author")));
   ow_->StartObject("")
@@ -734,8 +734,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("friend"),
-          StringPiece(
+          _, absl::string_view("friend"),
+          absl::string_view(
               "Starting an object in a repeated field but the parent object "
               "is not a list")))
       .With(Args<0>(HasObjectLocation("author")))
@@ -810,8 +810,8 @@
 
   EXPECT_CALL(
       listener_,
-      InvalidName(_, StringPiece("publisher"),
-                  StringPiece(
+      InvalidName(_, absl::string_view("publisher"),
+                  absl::string_view(
                       "Proto field is not repeating, cannot start list.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartObject("")
@@ -833,8 +833,8 @@
 TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtRoot) {
   Book empty;
 
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
-                                     StringPiece("Cannot find field.")))
+  EXPECT_CALL(listener_, InvalidName(_, absl::string_view("unknown"),
+                                     absl::string_view("Cannot find field.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject();
   CheckOutput(empty, 0);
@@ -851,8 +851,8 @@
   Author* luke = paul->add_friend_();
   luke->set_name("Luke");
 
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("address"),
-                                     StringPiece("Cannot find field.")))
+  EXPECT_CALL(listener_, InvalidName(_, absl::string_view("address"),
+                                     absl::string_view("Cannot find field.")))
       .With(Args<0>(HasObjectLocation("author.friend[1]")));
   ow_->StartObject("")
       ->StartObject("author")
@@ -877,8 +877,8 @@
 TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtRoot) {
   Book empty;
 
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
-                                     StringPiece("Cannot find field.")))
+  EXPECT_CALL(listener_, InvalidName(_, absl::string_view("unknown"),
+                                     absl::string_view("Cannot find field.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject();
   CheckOutput(empty, 0);
@@ -890,8 +890,8 @@
   author->set_name("William");
   author->add_pseudonym("Bill");
 
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("wife"),
-                                     StringPiece("Cannot find field.")))
+  EXPECT_CALL(listener_, InvalidName(_, absl::string_view("wife"),
+                                     absl::string_view("Cannot find field.")))
       .With(Args<0>(HasObjectLocation("author")));
   ow_->StartObject("")
       ->StartObject("author")
@@ -908,8 +908,8 @@
 TEST_P(ProtoStreamObjectWriterTest, UnknownListAtRoot) {
   Book empty;
 
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
-                                     StringPiece("Cannot find field.")))
+  EXPECT_CALL(listener_, InvalidName(_, absl::string_view("unknown"),
+                                     absl::string_view("Cannot find field.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartObject("")->StartList("unknown")->EndList()->EndObject();
   CheckOutput(empty, 0);
@@ -921,8 +921,8 @@
   Publisher* publisher = expected.mutable_publisher();
   publisher->set_name("propaganda");
 
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("alliance"),
-                                     StringPiece("Cannot find field.")))
+  EXPECT_CALL(listener_, InvalidName(_, absl::string_view("alliance"),
+                                     absl::string_view("Cannot find field.")))
       .With(Args<0>(HasObjectLocation("publisher")));
   ow_->StartObject("")
       ->StartObject("publisher")
@@ -987,8 +987,8 @@
   options_.ignore_unknown_fields = true;
   ResetProtoWriter();
 
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
-                                     StringPiece("Cannot find field.")))
+  EXPECT_CALL(listener_, InvalidName(_, absl::string_view("unknown"),
+                                     absl::string_view("Cannot find field.")))
       .Times(0);
   ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject();
   CheckOutput(empty, 0);
@@ -1056,10 +1056,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(_,
-                   StringPiece(
+                   absl::string_view(
                        "type.googleapis.com/"
                        "proto_util_converter.testing.Proto3Message.NestedEnum"),
-                   StringPiece("\"someunknownvalueyouwillneverknow\"")))
+                   absl::string_view("\"someunknownvalueyouwillneverknow\"")))
       .With(Args<0>(HasObjectLocation("enum_value")));
   ow_->StartObject("")
       ->RenderString("enumValue", "someunknownvalueyouwillneverknow")
@@ -1083,7 +1083,7 @@
   expected.set_title("My Title");
   expected.set_allocated_publisher(new Publisher());
 
-  EXPECT_CALL(listener_, MissingField(_, StringPiece("name")))
+  EXPECT_CALL(listener_, MissingField(_, absl::string_view("name")))
       .With(Args<0>(HasObjectLocation("publisher")));
   ow_->StartObject("")
       ->StartObject("publisher")
@@ -1096,8 +1096,8 @@
 TEST_P(ProtoStreamObjectWriterTest, InvalidFieldValueAtRoot) {
   Book empty;
 
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
-                                      StringPiece("\"garbage\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_UINT32"),
+                                      absl::string_view("\"garbage\"")))
       .With(Args<0>(HasObjectLocation("length")));
   ow_->StartObject("")->RenderString("length", "garbage")->EndObject();
   CheckOutput(empty, 0);
@@ -1107,11 +1107,11 @@
   Book expected;
   expected.set_title("My Title");
 
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
-                                      StringPiece("\"-400\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_UINT32"),
+                                      absl::string_view("\"-400\"")))
       .With(Args<0>(HasObjectLocation("length")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT64"),
-                                      StringPiece("\"3.14\"")))
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("TYPE_INT64"),
+                                      absl::string_view("\"3.14\"")))
       .With(Args<0>(HasObjectLocation("published")));
   ow_->StartObject("")
       ->RenderString("length", "-400")
@@ -1125,8 +1125,8 @@
   Book empty;
 
   EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Proto fields must have a name.")))
+              InvalidName(_, absl::string_view(""),
+                          absl::string_view("Proto fields must have a name.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartObject("")->RenderFloat("", 3.14)->EndObject();
   CheckOutput(empty, 0);
@@ -1138,8 +1138,8 @@
   expected.set_allocated_author(new Author());
 
   EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Proto fields must have a name.")))
+              InvalidName(_, absl::string_view(""),
+                          absl::string_view("Proto fields must have a name.")))
       .With(Args<0>(HasObjectLocation("author")));
   ow_->StartObject("")
       ->StartObject("author")
@@ -1155,8 +1155,8 @@
   expected.set_title("noname");
 
   EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Proto fields must have a name.")))
+              InvalidName(_, absl::string_view(""),
+                          absl::string_view("Proto fields must have a name.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartObject("")
       ->StartList("")
@@ -1172,8 +1172,8 @@
 
   EXPECT_CALL(
       listener_,
-      InvalidName(_, StringPiece("oops"),
-                  StringPiece("Root element should not be named.")))
+      InvalidName(_, absl::string_view("oops"),
+                  absl::string_view("Root element should not be named.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartObject("oops")->RenderString("title", "Annie")->EndObject();
   CheckOutput(expected, 7);
@@ -1184,8 +1184,8 @@
 
   EXPECT_CALL(
       listener_,
-      InvalidName(_, StringPiece("oops"),
-                  StringPiece("Root element should not be named.")))
+      InvalidName(_, absl::string_view("oops"),
+                  absl::string_view("Root element should not be named.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartList("oops")->RenderString("", "item")->EndList();
   CheckOutput(empty, 0);
@@ -1195,8 +1195,8 @@
   Book empty;
 
   EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Root element must be a message.")))
+              InvalidName(_, absl::string_view(""),
+                          absl::string_view("Root element must be a message.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->RenderBool("", true);
   CheckOutput(empty, 0);
@@ -1206,8 +1206,8 @@
   Book empty;
 
   EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece("oops"),
-                          StringPiece("Root element must be a message.")))
+              InvalidName(_, absl::string_view("oops"),
+                          absl::string_view("Root element must be a message.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->RenderBool("oops", true);
   CheckOutput(empty, 0);
@@ -1322,9 +1322,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2016-03-07T15:14:23+")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Illegal timestamp format; timestamps "
+              "must end with 'Z' or have a valid timezone offset.")));
 
   ow_->StartObject("")->RenderString("ts", "2016-03-07T15:14:23+")->EndObject();
   CheckOutput(timestamp);
@@ -1337,9 +1338,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2016-03-07T15:14:23+08-10")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Illegal timestamp format; timestamps "
+              "must end with 'Z' or have a valid timezone offset.")));
 
   ow_->StartObject("")
       ->RenderString("ts", "2016-03-07T15:14:23+08-10")
@@ -1354,9 +1356,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2016-03-07T15:14:23+24:10")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Illegal timestamp format; timestamps "
+              "must end with 'Z' or have a valid timezone offset.")));
 
   ow_->StartObject("")
       ->RenderString("ts", "2016-03-07T15:14:23+24:10")
@@ -1371,9 +1374,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2016-03-07T15:14:23+04:60")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Illegal timestamp format; timestamps "
+              "must end with 'Z' or have a valid timezone offset.")));
 
   ow_->StartObject("")
       ->RenderString("ts", "2016-03-07T15:14:23+04:60")
@@ -1387,8 +1391,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: ")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Illegal timestamp format; timestamps "
+              "must end with 'Z' or have a valid timezone offset.")));
 
   ow_->StartObject("")->RenderString("ts", "")->EndObject();
   CheckOutput(timestamp);
@@ -1400,8 +1406,9 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: Z")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view("Field 'ts', Invalid time format: Failed to "
+                            "parse input")));
 
   ow_->StartObject("")->RenderString("ts", "Z")->EndObject();
   CheckOutput(timestamp);
@@ -1413,9 +1420,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "1970-01-01T00:00:00.ABZ")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Invalid time format, failed to parse nano "
+              "seconds")));
 
   ow_->StartObject("")
       ->RenderString("ts", "1970-01-01T00:00:00.ABZ")
@@ -1429,9 +1437,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "-8031-10-18T00:00:00.000Z")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view("Field 'ts', Timestamp value exceeds limits")));
 
   ow_->StartObject("")
       ->RenderString("ts", "-8031-10-18T00:00:00.000Z")
@@ -1445,9 +1452,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2015-11-23T03:37:35.033155   Z")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Invalid time format, failed to parse nano "
+              "seconds")));
 
   ow_->StartObject("")
       // Whitespace in the Timestamp nanos is not allowed.
@@ -1462,9 +1470,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2015-11-23T03:37:35.033155 1234Z")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Invalid time format, failed to parse nano "
+              "seconds")));
 
   ow_->StartObject("")
       // Whitespace in the Timestamp nanos is not allowed.
@@ -1479,9 +1488,10 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2015-11-23T03:37:35.033abc155Z")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
+              "Field 'ts', Invalid time format, failed to parse nano "
+              "seconds")));
 
   ow_->StartObject("")
       // Non-numeric characters in the Timestamp nanos is not allowed.
@@ -1496,9 +1506,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "0-12-31T23:59:59.000Z")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view("Field 'ts', Timestamp value exceeds limits")));
 
   ow_->StartObject("")
       ->RenderString("ts", "0-12-31T23:59:59.000Z")
@@ -1522,8 +1531,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece(
+          _, absl::string_view("type.googleapis.com/google.protobuf.Duration"),
+          absl::string_view(
               "Field 'dur', Illegal duration format; duration must "
               "end with 's'")));
 
@@ -1537,8 +1546,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece(
+          _, absl::string_view("type.googleapis.com/google.protobuf.Duration"),
+          absl::string_view(
               "Field 'dur', Invalid duration format, failed to parse "
               "seconds")));
 
@@ -1552,8 +1561,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece("Field 'dur', Invalid duration format, failed to "
+          _, absl::string_view("type.googleapis.com/google.protobuf.Duration"),
+          absl::string_view("Field 'dur', Invalid duration format, failed to "
                             "parse nano seconds")));
 
   ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject();
@@ -1566,8 +1575,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece("Field 'dur', Duration value exceeds limits")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Duration"),
+          absl::string_view("Field 'dur', Duration value exceeds limits")));
 
   ow_->StartObject("")->RenderString("dur", "315576000002s")->EndObject();
   CheckOutput(duration);
@@ -1579,8 +1588,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece("Field 'dur', Duration value exceeds limits")));
+          _, absl::string_view("type.googleapis.com/google.protobuf.Duration"),
+          absl::string_view("Field 'dur', Duration value exceeds limits")));
 
   ow_->StartObject("")->RenderString("dur", "0.1000000001s")->EndObject();
   CheckOutput(duration);
@@ -1592,8 +1601,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece(
+          _, absl::string_view("type.googleapis.com/google.protobuf.Timestamp"),
+          absl::string_view(
               "Field 'ts', Invalid data type for timestamp, value is 1")))
       .With(Args<0>(HasObjectLocation("ts")));
   ow_->StartObject("")->RenderInt32("ts", 1)->EndObject();
@@ -1606,8 +1615,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece(
+          _, absl::string_view("type.googleapis.com/google.protobuf.Duration"),
+          absl::string_view(
               "Field 'dur', Invalid data type for duration, value is 1")))
       .With(Args<0>(HasObjectLocation("dur")));
   ow_->StartObject("")->RenderInt32("dur", 1)->EndObject();
@@ -1666,8 +1675,8 @@
 TEST_P(ProtoStreamObjectWriterStructTest, StructNullInputSuccess) {
   StructType struct_type;
   EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Proto fields must have a name.")))
+              InvalidName(_, absl::string_view(""),
+                          absl::string_view("Proto fields must have a name.")))
       .With(Args<0>(HasObjectLocation("")));
   ow_->StartObject("")->RenderNull("")->EndObject();
   CheckOutput(struct_type);
@@ -1678,8 +1687,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Struct"),
-          StringPiece("true")))
+          _, absl::string_view("type.googleapis.com/google.protobuf.Struct"),
+          absl::string_view("true")))
       .With(Args<0>(HasObjectLocation("object")));
 
   ow_->StartObject("")->RenderBool("object", true)->EndObject();
@@ -1710,8 +1719,8 @@
 
 TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) {
   EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece("gBike"),
-                          StringPiece(
+              InvalidName(_, absl::string_view("gBike"),
+                          absl::string_view(
                               "Repeated map key: 'gBike' is already set.")));
   ow_->StartObject("")
       ->StartObject("object")
@@ -1724,8 +1733,8 @@
 TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapListKeyTest) {
   EXPECT_CALL(
       listener_,
-      InvalidName(_, StringPiece("k1"),
-                  StringPiece("Repeated map key: 'k1' is already set.")));
+      InvalidName(_, absl::string_view("k1"),
+                  absl::string_view("Repeated map key: 'k1' is already set.")));
   ow_->StartObject("")
       ->StartObject("object")
       ->RenderString("k1", "v1")
@@ -1739,8 +1748,8 @@
 TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapObjectKeyTest) {
   EXPECT_CALL(
       listener_,
-      InvalidName(_, StringPiece("k1"),
-                  StringPiece("Repeated map key: 'k1' is already set.")));
+      InvalidName(_, absl::string_view("k1"),
+                  absl::string_view("Repeated map key: 'k1' is already set.")));
   ow_->StartObject("")
       ->StartObject("object")
       ->StartObject("k1")
@@ -1842,8 +1851,8 @@
   MapIn mm;
   EXPECT_CALL(
       listener_,
-      InvalidValue(_, StringPiece("Map"),
-                   StringPiece(
+      InvalidValue(_, absl::string_view("Map"),
+                   absl::string_view(
                        "Cannot bind a list to map for field 'map_input'.")));
   ow_->StartObject("")
       ->StartList("map_input")
@@ -1886,8 +1895,8 @@
 TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) {
   EXPECT_CALL(
       listener_,
-      InvalidName(_, StringPiece("k1"),
-                  StringPiece("Repeated map key: 'k1' is already set.")));
+      InvalidName(_, absl::string_view("k1"),
+                  absl::string_view("Repeated map key: 'k1' is already set.")));
   ow_->StartObject("")
       ->RenderString("other", "test")
       ->StartObject("map_input")
@@ -2051,7 +2060,7 @@
 }
 
 // Same as TypeUrlAtEnd, but use temporary string values to make sure we don't
-// mistakenly store StringPiece objects pointing to invalid memory.
+// mistakenly store absl::string_view objects pointing to invalid memory.
 TEST_P(ProtoStreamObjectWriterAnyTest, TypeUrlAtEndWithTemporaryStrings) {
   Book book;
   book.set_title("C++");
@@ -2120,8 +2129,8 @@
 
   EXPECT_CALL(
       listener_,
-      InvalidValue(_, StringPiece("Any"),
-                   StringPiece("Missing @type for any field in "
+      InvalidValue(_, absl::string_view("Any"),
+                   absl::string_view("Missing @type for any field in "
                                      "proto_util_converter.testing.AnyOut")));
 
   ow_->StartObject("")
@@ -2138,8 +2147,8 @@
 
   EXPECT_CALL(
       listener_,
-      InvalidValue(_, StringPiece("Any"),
-                   StringPiece("Missing @type for any field in "
+      InvalidValue(_, absl::string_view("Any"),
+                   absl::string_view("Missing @type for any field in "
                                      "proto_util_converter.testing.AnyOut")));
 
   ow_->StartObject("")
@@ -2156,8 +2165,8 @@
 
   EXPECT_CALL(
       listener_,
-      InvalidValue(_, StringPiece("Any"),
-                   StringPiece("Missing @type for any field in "
+      InvalidValue(_, absl::string_view("Any"),
+                   absl::string_view("Missing @type for any field in "
                                      "proto_util_converter.testing.AnyOut")));
 
   ow_->StartObject("")
@@ -2174,8 +2183,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("Any"),
-          StringPiece("Invalid type URL, type URLs must be of the form "
+          _, absl::string_view("Any"),
+          absl::string_view("Invalid type URL, type URLs must be of the form "
                             "'type.googleapis.com/<typename>', got: "
                             "type.other.com/some.Type")));
 
@@ -2192,8 +2201,8 @@
   AnyOut any;
 
   EXPECT_CALL(listener_,
-              InvalidValue(_, StringPiece("Any"),
-                           StringPiece(
+              InvalidValue(_, absl::string_view("Any"),
+                           absl::string_view(
                                "Invalid type URL, unknown type: some.Type")));
   ow_->StartObject("")
       ->StartObject("any")
@@ -2210,8 +2219,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(_,
-                   StringPiece("type.googleapis.com/google.protobuf.Any"),
-                   StringPiece("1")));
+                   absl::string_view("type.googleapis.com/google.protobuf.Any"),
+                   absl::string_view("1")));
   ow_->StartObject("")->RenderInt32("any", 1)->EndObject();
   CheckOutput(any);
 }
@@ -2225,8 +2234,12 @@
 }
 
 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
-                                      StringPiece("Invalid time format: ")));
+  EXPECT_CALL(listener_,
+              InvalidValue(_, absl::string_view("Any"),
+                           absl::string_view("Illegal timestamp format; "
+                                             "timestamps must end with "
+                                             "'Z' or have a valid "
+                                             "timezone offset.")));
 
   AnyOut any;
   google::protobuf::Any* any_type = any.mutable_any();
@@ -2337,8 +2350,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("Any"),
-          StringPiece("Expect a \"value\" field for well-known types.")));
+          _, absl::string_view("Any"),
+          absl::string_view("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");
@@ -2364,8 +2377,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("Any"),
-          StringPiece("Expect a \"value\" field for well-known types.")));
+          _, absl::string_view("Any"),
+          absl::string_view("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");
@@ -2392,8 +2405,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("Any"),
-          StringPiece("Expect a \"value\" field for well-known types.")));
+          _, absl::string_view("Any"),
+          absl::string_view("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");
@@ -2419,8 +2432,8 @@
 // }
 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForStruct) {
   EXPECT_CALL(listener_,
-              InvalidValue(_, StringPiece("Any"),
-                           StringPiece("Expect a JSON object.")));
+              InvalidValue(_, absl::string_view("Any"),
+                           absl::string_view("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");
@@ -2444,8 +2457,8 @@
 // }
 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForAny) {
   EXPECT_CALL(listener_,
-              InvalidValue(_, StringPiece("Any"),
-                           StringPiece("Expect a JSON object.")));
+              InvalidValue(_, absl::string_view("Any"),
+                           absl::string_view("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");
@@ -2704,8 +2717,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece("Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
+          _, absl::string_view("type.googleapis.com/google.protobuf.FieldMask"),
+          absl::string_view("Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
                             "Cannot find matching '(' for all ')'.")));
 
   ow_->StartObject("");
@@ -2718,8 +2731,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece(
+          _, absl::string_view("type.googleapis.com/google.protobuf.FieldMask"),
+          absl::string_view(
               "Field 'single_mask', Invalid FieldMask 'a(((b,c)'. Cannot "
               "find matching ')' for all '('.")));
 
@@ -2750,8 +2763,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece(
+          _, absl::string_view("type.googleapis.com/google.protobuf.FieldMask"),
+          absl::string_view(
               "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.")));
@@ -2766,8 +2779,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece("Field 'single_mask', Invalid FieldMask "
+          _, absl::string_view("type.googleapis.com/google.protobuf.FieldMask"),
+          absl::string_view("Field 'single_mask', Invalid FieldMask "
                             "'path.to.map[\"key1\"'. Map keys should be "
                             "represented as [\"some_key\"].")));
 
@@ -2780,8 +2793,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece("Field 'single_mask', Invalid FieldMask "
+          _, absl::string_view("type.googleapis.com/google.protobuf.FieldMask"),
+          absl::string_view("Field 'single_mask', Invalid FieldMask "
                             "'path.to.map[\"ke\"y1\"]'. Map keys should be "
                             "represented as [\"some_key\"].")));
 
@@ -2861,8 +2874,8 @@
   EXPECT_CALL(
       listener_,
       InvalidValue(
-          _, StringPiece("oneof"),
-          StringPiece(
+          _, absl::string_view("oneof"),
+          absl::string_view(
               "oneof field 'data' is already set. Cannot set 'intData'")));
 
   ow_->StartObject("");
@@ -2874,8 +2887,8 @@
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForMessageTypesPrimitiveFirstTest) {
   // Test for setting primitive oneof field first and then message field.
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'messageData'")));
 
@@ -2891,8 +2904,8 @@
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForMessageTypesMessageFirstTest) {
   // Test for setting message oneof field first and then primitive field.
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'strData'")));
 
@@ -2907,8 +2920,8 @@
 
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForStructTypesPrimitiveFirstTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'structData'")));
 
@@ -2923,8 +2936,8 @@
 
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForStructTypesStructFirstTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'strData'")));
 
@@ -2939,8 +2952,8 @@
 
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForStructValueTypesTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'valueData'")));
 
@@ -2957,8 +2970,8 @@
 
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'tsData'")));
 
@@ -2971,8 +2984,8 @@
 
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForWellKnownTypesWktFirstTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'intData'")));
 
@@ -2985,8 +2998,8 @@
 
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForWellKnownTypesAndMessageTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'messageData'")));
 
@@ -3002,8 +3015,8 @@
 
 TEST_P(ProtoStreamObjectWriterOneOfsTest,
        MultipleOneofsFailForOneofWithinAnyTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
+  EXPECT_CALL(listener_, InvalidValue(_, absl::string_view("oneof"),
+                                      absl::string_view(
                                           "oneof field 'data' is already set. "
                                           "Cannot set 'intData'")));
 
diff --git a/src/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h
index f6f7c89..9fe59e3 100644
--- a/src/google/protobuf/util/internal/structured_objectwriter.h
+++ b/src/google/protobuf/util/internal/structured_objectwriter.h
@@ -33,12 +33,12 @@
 
 #include <memory>
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/util/internal/object_writer.h>
+#include "absl/base/casts.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/util/internal/object_writer.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -58,6 +58,8 @@
 // Derived classes could be thread-unsafe.
 class PROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter {
  public:
+  StructuredObjectWriter(const StructuredObjectWriter&) = delete;
+  StructuredObjectWriter& operator=(const StructuredObjectWriter&) = delete;
   ~StructuredObjectWriter() override {}
 
  protected:
@@ -72,12 +74,15 @@
     explicit BaseElement(BaseElement* parent)
         : parent_(parent),
           level_(parent == nullptr ? 0 : parent->level() + 1) {}
+    BaseElement() = delete;
+    BaseElement(const BaseElement&) = delete;
+    BaseElement& operator=(const BaseElement&) = delete;
     virtual ~BaseElement() {}
 
     // Releases ownership of the parent and returns a pointer to it.
     template <typename ElementType>
     ElementType* pop() {
-      return down_cast<ElementType*>(parent_.release());
+      return google::protobuf::internal::DownCast<ElementType*>(parent_.release());
     }
 
     // Returns true if this element is the root.
@@ -97,8 +102,6 @@
     // 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() {}
@@ -108,7 +111,6 @@
 
  private:
   // Do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StructuredObjectWriter);
 };
 
 }  // namespace converter
@@ -116,6 +118,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_STRUCTURED_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc
index b6cf536..927fb93 100644
--- a/src/google/protobuf/util/internal/type_info.cc
+++ b/src/google/protobuf/util/internal/type_info.cc
@@ -28,19 +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/util/internal/type_info.h>
+#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>
+#include "google/protobuf/type.pb.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/util/internal/utility.h"
 
 namespace google {
 namespace protobuf {
@@ -59,19 +56,18 @@
     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);
+  absl::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
+      absl::string_view type_url) const override {
+    auto 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.
+    // Stores the string value so it can be referenced using absl::string_view
+    // 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 =
+    absl::Status status =
         type_resolver_->ResolveMessageType(string_type_url, type.get());
     StatusOrType result =
         status.ok() ? StatusOrType(type.release()) : StatusOrType(status);
@@ -80,25 +76,25 @@
   }
 
   const google::protobuf::Type* GetTypeByTypeUrl(
-      StringPiece type_url) const override {
+      absl::string_view 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 =
+      absl::string_view type_url) const override {
+    std::map<absl::string_view, 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.
+    // Stores the string value so it can be referenced using absl::string_view
+    // 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 =
+    absl::Status status =
         type_resolver_->ResolveEnumType(string_type_url, enum_type.get());
     StatusOrEnum result =
         status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status);
@@ -108,30 +104,29 @@
 
   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);
+      absl::string_view camel_case_name) const override {
+    auto it = indexed_types_.find(type);
     const CamelCaseNameTable& camel_case_name_table =
-        (it == indexed_types_.end())
+        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;
+
+    absl::string_view name = camel_case_name;
+    auto cc_it = camel_case_name_table.find(name);
+    if (cc_it != camel_case_name_table.end()) {
+      name = cc_it->second;
     }
     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;
+  typedef absl::StatusOr<const google::protobuf::Type*> StatusOrType;
+  typedef absl::StatusOr<const google::protobuf::Enum*> StatusOrEnum;
+  typedef std::map<absl::string_view, absl::string_view> CamelCaseNameTable;
 
   template <typename T>
-  static void DeleteCachedTypes(std::map<StringPiece, T>* cached_types) {
-    for (typename std::map<StringPiece, T>::iterator it =
+  static void DeleteCachedTypes(std::map<absl::string_view, T>* cached_types) {
+    for (typename std::map<absl::string_view, T>::iterator it =
              cached_types->begin();
          it != cached_types->end(); ++it) {
       if (it->second.ok()) {
@@ -145,14 +140,13 @@
       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
-                     << "'.";
+      absl::string_view existing =
+          camel_case_name_table->insert({field.json_name(), field.name()})
+              .first->second;
+      if (existing != field.name()) {
+        GOOGLE_LOG(WARNING) << "Field '" << field.name() << "' and '" << existing
+                     << "' map to the same camel case name '"
+                     << field.json_name() << "'.";
       }
     }
     return *camel_case_name_table;
@@ -164,8 +158,8 @@
   // 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<absl::string_view, StatusOrType> cached_types_;
+  mutable std::map<absl::string_view, StatusOrEnum> cached_enums_;
 
   mutable std::map<const google::protobuf::Type*, CamelCaseNameTable>
       indexed_types_;
diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h
index 257df5b..801bfba 100644
--- a/src/google/protobuf/util/internal/type_info.h
+++ b/src/google/protobuf/util/internal/type_info.h
@@ -31,15 +31,16 @@
 #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>
+#include "google/protobuf/type.pb.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/util/type_resolver.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -50,6 +51,8 @@
 class PROTOBUF_EXPORT TypeInfo {
  public:
   TypeInfo() {}
+  TypeInfo(const TypeInfo&) = delete;
+  TypeInfo& operator=(const TypeInfo&) = delete;
   virtual ~TypeInfo() {}
 
   // Resolves a type url into a Type. If the type url is invalid, returns
@@ -57,34 +60,31 @@
   // 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;
+  virtual absl::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
+      absl::string_view 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;
+      absl::string_view 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;
+      absl::string_view 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;
+      absl::string_view 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
@@ -92,6 +92,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 088f412..e73efae 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.cc
+++ b/src/google/protobuf/util/internal/type_info_test_helper.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/util/internal/type_info_test_helper.h>
+#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>
+#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 {
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h
index 1110a34..9999c2c 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.h
+++ b/src/google/protobuf/util/internal/type_info_test_helper.h
@@ -34,13 +34,13 @@
 #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>
+#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 {
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index 918ee17..f8054ca 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -28,26 +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/utility.h>
+#include "google/protobuf/util/internal/utility.h"
 
 #include <algorithm>
 #include <cmath>
 #include <cstdint>
+#include <iterator>
 #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>
+#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 "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/util/internal/constants.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 {
@@ -56,7 +59,7 @@
 
 bool GetBoolOptionOrDefault(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, bool default_value) {
+    absl::string_view option_name, bool default_value) {
   const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
   if (opt == nullptr) {
     return default_value;
@@ -66,7 +69,7 @@
 
 int64_t GetInt64OptionOrDefault(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, int64_t default_value) {
+    absl::string_view option_name, int64_t default_value) {
   const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
   if (opt == nullptr) {
     return default_value;
@@ -76,7 +79,7 @@
 
 double GetDoubleOptionOrDefault(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, double default_value) {
+    absl::string_view option_name, double default_value) {
   const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
   if (opt == nullptr) {
     return default_value;
@@ -86,7 +89,7 @@
 
 std::string GetStringOptionOrDefault(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, StringPiece default_value) {
+    absl::string_view option_name, absl::string_view default_value) {
   const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
   if (opt == nullptr) {
     return std::string(default_value);
@@ -125,7 +128,7 @@
   return s.value();
 }
 
-const StringPiece GetTypeWithoutUrl(StringPiece type_url) {
+absl::string_view GetTypeWithoutUrl(absl::string_view type_url) {
   if (type_url.size() > kTypeUrlSize && type_url[kTypeUrlSize] == '/') {
     return type_url.substr(kTypeUrlSize + 1);
   } else {
@@ -137,13 +140,13 @@
   }
 }
 
-const std::string GetFullTypeWithUrl(StringPiece simple_type) {
-  return StrCat(kTypeServiceBaseUrl, "/", simple_type);
+std::string GetFullTypeWithUrl(absl::string_view simple_type) {
+  return absl::StrCat(kTypeServiceBaseUrl, "/", simple_type);
 }
 
 const google::protobuf::Option* FindOptionOrNull(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name) {
+    absl::string_view option_name) {
   for (int i = 0; i < options.size(); ++i) {
     const google::protobuf::Option& opt = options.Get(i);
     if (opt.name() == option_name) {
@@ -154,7 +157,7 @@
 }
 
 const google::protobuf::Field* FindFieldInTypeOrNull(
-    const google::protobuf::Type* type, StringPiece field_name) {
+    const google::protobuf::Type* type, absl::string_view field_name) {
   if (type != nullptr) {
     for (int i = 0; i < type->fields_size(); ++i) {
       const google::protobuf::Field& field = type->fields(i);
@@ -167,7 +170,7 @@
 }
 
 const google::protobuf::Field* FindJsonFieldInTypeOrNull(
-    const google::protobuf::Type* type, StringPiece json_name) {
+    const google::protobuf::Type* type, absl::string_view json_name) {
   if (type != nullptr) {
     for (int i = 0; i < type->fields_size(); ++i) {
       const google::protobuf::Field& field = type->fields(i);
@@ -193,7 +196,7 @@
 }
 
 const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
-    const google::protobuf::Enum* enum_type, StringPiece enum_name) {
+    const google::protobuf::Enum* enum_type, absl::string_view 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);
@@ -219,7 +222,7 @@
 }
 
 const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull(
-    const google::protobuf::Enum* enum_type, StringPiece enum_name) {
+    const google::protobuf::Enum* enum_type, absl::string_view 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);
@@ -233,7 +236,7 @@
       // 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);
+        *it = absl::ascii_toupper(*it);
       }
 
       if (enum_name_without_underscore == enum_name) {
@@ -244,14 +247,11 @@
   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 EnumValueNameToLowerCamelCase(absl::string_view input) {
+  return ToCamelCase(absl::AsciiStrToLower(input));
 }
 
-std::string ToCamelCase(StringPiece input) {
+std::string ToCamelCase(absl::string_view input) {
   bool capitalize_next = false;
   bool was_cap = true;
   bool is_cap = false;
@@ -260,7 +260,7 @@
   result.reserve(input.size());
 
   for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) {
-    is_cap = ascii_isupper(input[i]);
+    is_cap = absl::ascii_isupper(input[i]);
     if (input[i] == '_') {
       capitalize_next = true;
       if (!result.empty()) first_word = false;
@@ -272,37 +272,37 @@
       // 2) followed by a lowercase: "...ABc..."
       if (!result.empty() && is_cap &&
           (!was_cap ||
-           (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
+           (i + 1 < input.size() && absl::ascii_islower(input[i + 1])))) {
         first_word = false;
         result.push_back(input[i]);
       } else {
-        result.push_back(ascii_tolower(input[i]));
+        result.push_back(absl::ascii_tolower(input[i]));
         continue;
       }
     } else if (capitalize_next) {
       capitalize_next = false;
-      if (ascii_islower(input[i])) {
-        result.push_back(ascii_toupper(input[i]));
+      if (absl::ascii_islower(input[i])) {
+        result.push_back(absl::ascii_toupper(input[i]));
         continue;
       } else {
         result.push_back(input[i]);
         continue;
       }
     } else {
-      result.push_back(ascii_tolower(input[i]));
+      result.push_back(absl::ascii_tolower(input[i]));
     }
   }
   return result;
 }
 
-std::string ToSnakeCase(StringPiece input) {
+std::string ToSnakeCase(absl::string_view 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])) {
+    if (absl::ascii_isupper(input[i])) {
       // Consider when the current character B is capitalized:
       // 1) At beginning of input:   "B..." => "b..."
       //    (e.g. "Biscuit" => "biscuit")
@@ -315,11 +315,11 @@
       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
+            absl::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]));
+      result.push_back(absl::ascii_tolower(input[i]));
       was_not_underscore = true;
       was_not_cap = false;
     } else {
@@ -331,8 +331,8 @@
   return result;
 }
 
-std::set<std::string>* well_known_types_ = nullptr;
-PROTOBUF_NAMESPACE_ID::internal::once_flag well_known_types_init_;
+absl::flat_hash_set<absl::string_view>* well_known_types_ = nullptr;
+absl::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",
@@ -344,20 +344,18 @@
 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]);
-  }
+  well_known_types_ = new absl::flat_hash_set<absl::string_view>(
+      std::begin(well_known_types_name_array_),
+      std::end(well_known_types_name_array_));
   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);
+  absl::call_once(well_known_types_init_, InitWellKnownTypes);
+  return well_known_types_->contains(type_name);
 }
 
-bool IsValidBoolString(StringPiece bool_string) {
+bool IsValidBoolString(absl::string_view bool_string) {
   return bool_string == "true" || bool_string == "false" ||
          bool_string == "1" || bool_string == "0";
 }
@@ -392,7 +390,7 @@
   return DoubleAsString(value);
 }
 
-bool SafeStrToFloat(StringPiece str, float* value) {
+bool SafeStrToFloat(absl::string_view str, float* value) {
   double double_value;
   if (!safe_strtod(str, &double_value)) {
     return false;
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
index 79d6779..552873d 100644
--- a/src/google/protobuf/util/internal/utility.h
+++ b/src/google/protobuf/util/internal/utility.h
@@ -36,17 +36,20 @@
 #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>
+#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 "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -61,25 +64,25 @@
 // 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);
+    absl::string_view 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);
+    absl::string_view 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);
+    absl::string_view 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);
+    absl::string_view option_name, absl::string_view default_value);
 
 // Returns a boolean value contained in Any type.
 // TODO(skarvaje): Make these utilities dealing with Any types more generic,
@@ -98,8 +101,8 @@
 
 // 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);
+PROTOBUF_EXPORT absl::string_view GetTypeWithoutUrl(
+    absl::string_view type_url);
 
 // Returns the simple_type with the base type url (kTypeServiceBaseUrl)
 // prefixed.
@@ -107,24 +110,24 @@
 // E.g:
 // GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string
 // "type.googleapis.com/google.protobuf.Timestamp".
-PROTOBUF_EXPORT const std::string GetFullTypeWithUrl(
-    StringPiece simple_type);
+PROTOBUF_EXPORT std::string GetFullTypeWithUrl(
+    absl::string_view 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);
+    absl::string_view 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);
+    const google::protobuf::Type* type, absl::string_view 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);
+    const google::protobuf::Type* type, absl::string_view json_name);
 
 // Similar to FindFieldInTypeOrNull, but this looks up fields by number.
 const google::protobuf::Field* FindFieldInTypeByNumberOrNull(
@@ -133,7 +136,7 @@
 // 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);
+    const google::protobuf::Enum* enum_type, absl::string_view enum_name);
 
 // Finds and returns the EnumValue identified by value in the passed tech
 // Enum object. Returns nullptr if none found.
@@ -145,23 +148,23 @@
 // 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);
+    const google::protobuf::Enum* enum_type, absl::string_view enum_name);
 
 // Converts input to camel-case and returns it.
-PROTOBUF_EXPORT std::string ToCamelCase(const StringPiece input);
+PROTOBUF_EXPORT std::string ToCamelCase(const absl::string_view input);
 
 // Converts enum name string to camel-case and returns it.
-std::string EnumValueNameToLowerCamelCase(const StringPiece input);
+std::string EnumValueNameToLowerCamelCase(const absl::string_view input);
 
 // Converts input to snake_case and returns it.
-PROTOBUF_EXPORT std::string ToSnakeCase(StringPiece input);
+PROTOBUF_EXPORT std::string ToSnakeCase(absl::string_view 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);
+PROTOBUF_EXPORT bool IsValidBoolString(absl::string_view bool_string);
 
 // Returns true if "field" is a protobuf map field based on its type.
 PROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field,
@@ -177,7 +180,7 @@
 // Convert from int32, int64, uint32, uint64, double or float to string.
 template <typename T>
 std::string ValueAsString(T value) {
-  return StrCat(value);
+  return absl::StrCat(value);
 }
 
 template <>
@@ -192,13 +195,13 @@
 
 // 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);
+PROTOBUF_EXPORT bool SafeStrToFloat(absl::string_view str, float* value);
 
 }  // namespace converter
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_UTILITY_H__
diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto
index 0eec9da..4df5eb9 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;
 }
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index c39c10d..8df4733 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -28,67 +28,43 @@
 // (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/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>
+#include "absl/base/call_once.h"
+#include "absl/status/status.h"
+#include "google/protobuf/stubs/bytestream.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_sink.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>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
+
 namespace google {
 namespace protobuf {
 namespace util {
+using ::google::protobuf::io::zc_sink_internal::ZeroCopyStreamByteSink;
 
-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,
+absl::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));
@@ -114,7 +90,7 @@
   }
 }
 
-util::Status BinaryToJsonString(TypeResolver* resolver,
+absl::Status BinaryToJsonString(TypeResolver* resolver,
                                 const std::string& type_url,
                                 const std::string& binary_input,
                                 std::string* json_output,
@@ -129,59 +105,60 @@
 class StatusErrorListener : public converter::ErrorListener {
  public:
   StatusErrorListener() {}
+  StatusErrorListener(const StatusErrorListener&) = delete;
+  StatusErrorListener& operator=(const StatusErrorListener&) = delete;
   ~StatusErrorListener() override {}
 
-  util::Status GetStatus() { return status_; }
+  absl::Status GetStatus() { return status_; }
 
   void InvalidName(const converter::LocationTrackerInterface& loc,
-                   StringPiece unknown_name,
-                   StringPiece message) override {
+                   absl::string_view unknown_name,
+                   absl::string_view message) override {
     std::string loc_string = GetLocString(loc);
     if (!loc_string.empty()) {
       loc_string.append(" ");
     }
-    status_ = util::InvalidArgumentError(
-        StrCat(loc_string, unknown_name, ": ", message));
+    status_ = absl::InvalidArgumentError(
+        absl::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),
+                    absl::string_view type_name,
+                    absl::string_view value) override {
+    status_ = absl::InvalidArgumentError(
+        absl::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(
+                    absl::string_view missing_name) override {
+    status_ = absl::InvalidArgumentError(absl::StrCat(
         GetLocString(loc), ": missing field ", std::string(missing_name)));
   }
 
  private:
-  util::Status status_;
+  absl::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, ")");
+      loc_string = absl::StrCat("(", loc_string, ")");
     }
     return loc_string;
   }
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StatusErrorListener);
 };
 }  // namespace
 
-util::Status JsonToBinaryStream(TypeResolver* resolver,
+absl::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);
+  ZeroCopyStreamByteSink sink(binary_output);
   StatusErrorListener listener;
   converter::ProtoStreamObjectWriter::Options proto_writer_options;
   proto_writer_options.ignore_unknown_fields = options.ignore_unknown_fields;
@@ -191,6 +168,7 @@
       options.case_insensitive_enum_parsing;
   converter::ProtoStreamObjectWriter proto_writer(
       resolver, type, &sink, &listener, proto_writer_options);
+  proto_writer.set_use_strict_base64_decoding(false);
 
   converter::JsonStreamParser parser(&proto_writer);
   const void* buffer;
@@ -198,16 +176,16 @@
   while (json_input->Next(&buffer, &length)) {
     if (length == 0) continue;
     RETURN_IF_ERROR(parser.Parse(
-        StringPiece(static_cast<const char*>(buffer), length)));
+        absl::string_view(static_cast<const char*>(buffer), length)));
   }
   RETURN_IF_ERROR(parser.FinishParse());
 
   return listener.GetStatus();
 }
 
-util::Status JsonToBinaryString(TypeResolver* resolver,
+absl::Status JsonToBinaryString(TypeResolver* resolver,
                                 const std::string& type_url,
-                                StringPiece json_input,
+                                absl::string_view json_input,
                                 std::string* binary_output,
                                 const JsonParseOptions& options) {
   io::ArrayInputStream input_stream(json_input.data(), json_input.size());
@@ -219,7 +197,7 @@
 namespace {
 const char* kTypeUrlPrefix = "type.googleapis.com";
 TypeResolver* generated_type_resolver_ = nullptr;
-PROTOBUF_NAMESPACE_ID::internal::once_flag generated_type_resolver_init_;
+absl::once_flag generated_type_resolver_init_;
 
 std::string GetTypeUrl(const Message& message) {
   return std::string(kTypeUrlPrefix) + "/" +
@@ -237,20 +215,20 @@
 }
 
 TypeResolver* GetGeneratedTypeResolver() {
-  PROTOBUF_NAMESPACE_ID::internal::call_once(generated_type_resolver_init_,
-                                             InitGeneratedTypeResolver);
+  absl::call_once(generated_type_resolver_init_, InitGeneratedTypeResolver);
   return generated_type_resolver_;
 }
 }  // namespace
 
-util::Status MessageToJsonString(const Message& message, std::string* output,
+absl::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 =
+  absl::Status result =
       BinaryToJsonString(resolver, GetTypeUrl(message),
                          message.SerializeAsString(), output, options);
   if (pool != DescriptorPool::generated_pool()) {
@@ -259,18 +237,19 @@
   return result;
 }
 
-util::Status JsonStringToMessage(StringPiece input, Message* message,
+absl::Status JsonStringToMessage(absl::string_view 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),
+  absl::Status result = JsonToBinaryString(resolver, GetTypeUrl(*message),
                                            input, &binary, options);
   if (result.ok() && !message->ParseFromString(binary)) {
-    result = util::InvalidArgumentError(
+    result = absl::InvalidArgumentError(
         "JSON transcoder produced invalid protobuf output.");
   }
   if (pool != DescriptorPool::generated_pool()) {
diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
index 0f1c4d8..5ee4f83 100644
--- a/src/google/protobuf/util/json_util.h
+++ b/src/google/protobuf/util/json_util.h
@@ -33,14 +33,15 @@
 #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 "google/protobuf/stubs/bytestream.h"
+#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>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -93,11 +94,14 @@
 // 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,
+//
+// 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 JsonOptions& options);
 
-inline util::Status MessageToJsonString(const Message& message,
+inline absl::Status MessageToJsonString(const Message& message,
                                         std::string* output) {
   return MessageToJsonString(message, output, JsonOptions());
 }
@@ -105,10 +109,13 @@
 // 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);
+//
+// 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 JsonParseOptions& options);
 
-inline util::Status JsonStringToMessage(StringPiece input,
+inline absl::Status JsonStringToMessage(absl::string_view input,
                                         Message* message) {
   return JsonStringToMessage(input, message, JsonParseOptions());
 }
@@ -119,12 +126,15 @@
 //   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(
+//
+// 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(
     TypeResolver* resolver, const std::string& type_url,
     io::ZeroCopyInputStream* binary_input,
     io::ZeroCopyOutputStream* json_output, const JsonPrintOptions& options);
 
-inline util::Status BinaryToJsonStream(TypeResolver* resolver,
+inline absl::Status BinaryToJsonStream(TypeResolver* resolver,
                                        const std::string& type_url,
                                        io::ZeroCopyInputStream* binary_input,
                                        io::ZeroCopyOutputStream* json_output) {
@@ -132,12 +142,12 @@
                             JsonPrintOptions());
 }
 
-PROTOBUF_EXPORT util::Status BinaryToJsonString(
+PROTOBUF_EXPORT absl::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,
+inline absl::Status BinaryToJsonString(TypeResolver* resolver,
                                        const std::string& type_url,
                                        const std::string& binary_input,
                                        std::string* json_output) {
@@ -150,12 +160,15 @@
 //   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(
+//
+// 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(
     TypeResolver* resolver, const std::string& type_url,
     io::ZeroCopyInputStream* json_input,
     io::ZeroCopyOutputStream* binary_output, const JsonParseOptions& options);
 
-inline util::Status JsonToBinaryStream(
+inline absl::Status JsonToBinaryStream(
     TypeResolver* resolver, const std::string& type_url,
     io::ZeroCopyInputStream* json_input,
     io::ZeroCopyOutputStream* binary_output) {
@@ -163,42 +176,22 @@
                             JsonParseOptions());
 }
 
-PROTOBUF_EXPORT util::Status JsonToBinaryString(
+PROTOBUF_EXPORT absl::Status JsonToBinaryString(
     TypeResolver* resolver, const std::string& type_url,
-    StringPiece json_input, std::string* binary_output,
+    absl::string_view json_input, std::string* binary_output,
     const JsonParseOptions& options);
 
-inline util::Status JsonToBinaryString(TypeResolver* resolver,
+inline absl::Status JsonToBinaryString(TypeResolver* resolver,
                                        const std::string& type_url,
-                                       StringPiece json_input,
+                                       absl::string_view 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
-
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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
index 7216199..3f18431 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -28,175 +28,321 @@
 // (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/util/json_util.h"
 
+#include <algorithm>
 #include <cstdint>
 #include <list>
+#include <memory>
 #include <string>
+#include <vector>
 
-#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 "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 "google/protobuf/unittest.pb.h"
+#include <gmock/gmock.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>
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/escaping.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/internal/testdata/maps.pb.h"
+#include "google/protobuf/util/json_format.pb.h"
+#include "google/protobuf/util/json_format.pb.h"
+#include "google/protobuf/util/json_format_proto3.pb.h"
+#include "google/protobuf/util/json_format_proto3.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"
+
+bool IsJson2() {
+  // Pay no attention to the person behind the curtain.
+  return false;
+}
 
 namespace google {
 namespace protobuf {
 namespace util {
 namespace {
+using ::proto3::TestAny;
+using ::proto3::TestEnumValue;
+using ::proto3::TestMap;
+using ::proto3::TestMessage;
+using ::proto3::TestOneof;
+using ::proto3::TestWrapper;
+using ::proto_util_converter::testing::MapIn;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::Not;
+using ::testing::Pair;
+using ::testing::SizeIs;
 
-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;
+// 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);
+}
 
-// 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 {
+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:
-  JsonUtilTest() {}
+  absl::StatusOr<std::string> ToJson(const Message& proto,
+                                     JsonPrintOptions 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 ToJson(const Message& message, const JsonPrintOptions& options) {
     std::string result;
-    GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options));
+    io::StringOutputStream out(&result);
+
+    RETURN_IF_ERROR(BinaryToJsonStream(
+        resolver_.get(),
+        absl::StrCat("type.googleapis.com/", proto.GetTypeName()), &in, &out,
+        options));
     return result;
   }
 
-  bool FromJson(const std::string& json, Message* message,
-                const JsonParseOptions& options) {
-    return JsonStringToMessage(json, message, options).ok();
+  // 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,
+                       JsonParseOptions 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();
   }
 
-  bool FromJson(const std::string& json, Message* message) {
-    return FromJson(json, message, JsonParseOptions());
+  template <typename Proto>
+  absl::StatusOr<Proto> ToProto(absl::string_view json,
+                                JsonParseOptions options = {}) {
+    Proto proto;
+    RETURN_IF_ERROR(ToProto(proto, json, options));
+    return proto;
   }
 
-  std::unique_ptr<TypeResolver> resolver_;
+  std::unique_ptr<TypeResolver> resolver_{NewTypeResolverForDescriptorPool(
+      "type.googleapis.com", DescriptorPool::generated_pool())};
 };
 
-TEST_F(JsonUtilTest, TestWhitespaces) {
+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]})"));
 
   JsonPrintOptions options;
-  EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options));
   options.add_whitespace = true;
-  EXPECT_EQ(
-      "{\n"
-      " \"messageValue\": {}\n"
-      "}\n",
-      ToJson(m, options));
+  // Note: whitespace here is significant.
+  EXPECT_THAT(ToJson(m, options), IsOkAndHolds(R"({
+ "stringValue": "foo",
+ "messageValue": {},
+ "repeatedBoolValue": [
+  true,
+  false
+ ]
+}
+)"));
 }
 
-TEST_F(JsonUtilTest, TestDefaultValues) {
+TEST_P(JsonTest, TestDefaultValues) {
   TestMessage m;
+  EXPECT_THAT(ToJson(m), IsOkAndHolds("{}"));
+
   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));
+  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\":[]"
+                                               "}"));
 
-  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));
+  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\":[]"
+                   "}"));
 
-  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));
+  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"})"));
+
+  // The ESF parser actually gets this wrong, and serializes floats whose
+  // default value is non-finite as 0. We make sure to reproduce this bug.
+  if (IsJson2()) {
+    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}"})"));
+  } else {
+    EXPECT_THAT(
+        ToJson(protobuf_unittest::TestExtremeDefaultValues(), options),
+        IsOkAndHolds(
+            R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")"
+            R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)"
+            R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807")"
+            R"(,"reallySmallInt32":-2147483648,"reallySmallInt64":"-9223372036854775808",)"
+            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":"? ? ?? ?? ??? ??/ ??-","stringWithZero":"hel\u0000lo")"
+            R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")"
+            R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})"));
+  }
 }
 
-TEST_F(JsonUtilTest, TestPreserveProtoFieldNames) {
+TEST_P(JsonTest, TestPreserveProtoFieldNames) {
   TestMessage m;
   m.mutable_message_value();
 
   JsonPrintOptions options;
   options.preserve_proto_field_names = true;
-  EXPECT_EQ("{\"message_value\":{}}", ToJson(m, options));
+  EXPECT_THAT(ToJson(m, options), IsOkAndHolds("{\"message_value\":{}}"));
+
 }
 
-TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
+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);
@@ -205,20 +351,19 @@
   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));
+  auto printed = ToJson(orig, print_options);
+  ASSERT_THAT(printed,
+              IsOkAndHolds("{\"enumValue\":1,\"repeatedEnumValue\":[0,1]}"));
 
-  TestMessage parsed;
-  JsonParseOptions parse_options;
-  ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
+  auto parsed = ToProto<TestMessage>(*printed);
+  ASSERT_OK(parsed);
 
-  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));
+  EXPECT_EQ(parsed->enum_value(), proto3::BAR);
+  EXPECT_THAT(parsed->repeated_enum_value(),
+              ElementsAre(proto3::FOO, proto3::BAR));
 }
 
-TEST_F(JsonUtilTest, TestPrintEnumsAsIntsWithDefaultValue) {
+TEST_P(JsonTest, TestPrintEnumsAsIntsWithDefaultValue) {
   TestEnumValue orig;
   // orig.set_enum_value1(proto3::FOO)
   orig.set_enum_value2(proto3::FOO);
@@ -228,133 +373,270 @@
   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));
+  auto printed = ToJson(orig, print_options);
+  ASSERT_THAT(
+      printed,
+      IsOkAndHolds("{\"enumValue1\":0,\"enumValue2\":0,\"enumValue3\":1}"));
 
-  TestEnumValue parsed;
-  JsonParseOptions parse_options;
-  ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
+  auto parsed = ToProto<TestEnumValue>(*printed);
 
-  EXPECT_EQ(proto3::FOO, parsed.enum_value1());
-  EXPECT_EQ(proto3::FOO, parsed.enum_value2());
-  EXPECT_EQ(proto3::BAR, parsed.enum_value3());
+  EXPECT_EQ(parsed->enum_value1(), proto3::FOO);
+  EXPECT_EQ(parsed->enum_value2(), proto3::FOO);
+  EXPECT_EQ(parsed->enum_value3(), proto3::BAR);
 }
 
-TEST_F(JsonUtilTest, TestPrintProto2EnumAsIntWithDefaultValue) {
+TEST_P(JsonTest, 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));
+  auto printed = ToJson(orig, print_options);
+  ASSERT_THAT(printed, IsOkAndHolds("{\"enumValue\":2}"));
 
-  protobuf_unittest::TestDefaultEnumValue parsed;
-  JsonParseOptions parse_options;
-  ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
+  auto parsed = ToProto<protobuf_unittest::TestDefaultEnumValue>(*printed);
+  ASSERT_OK(parsed);
 
-  EXPECT_EQ(protobuf_unittest::DEFAULT, parsed.enum_value());
+  EXPECT_EQ(parsed->enum_value(), protobuf_unittest::DEFAULT);
 }
 
-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_P(JsonTest, QuotedEnumValue) {
+  auto m = ToProto<TestEnumValue>(R"json(
+    {"enumValue1": "1"}
+  )json");
+  ASSERT_OK(m);
+  EXPECT_THAT(m->enum_value1(), proto3::BAR);
 }
 
-TEST_F(JsonUtilTest, ParseMap) {
+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, 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;
-  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());
+  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_F(JsonUtilTest, ParsePrimitiveMapIn) {
+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;
   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());
+  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_F(JsonUtilTest, PrintPrimitiveOneof) {
+TEST_P(JsonTest, PrintPrimitiveOneof) {
   TestOneof message;
   JsonPrintOptions options;
   options.always_print_primitive_fields = true;
   message.mutable_oneof_message_value();
-  EXPECT_EQ("{\"oneofMessageValue\":{\"value\":0}}", ToJson(message, options));
+  EXPECT_THAT(ToJson(message, options),
+              IsOkAndHolds(R"({"oneofMessageValue":{"value":0}})"));
 
   message.set_oneof_int32_value(1);
-  EXPECT_EQ("{\"oneofInt32Value\":1}", ToJson(message, options));
+  EXPECT_THAT(ToJson(message, options),
+              IsOkAndHolds(R"({"oneofInt32Value":1})"));
 }
 
-TEST_F(JsonUtilTest, TestParseIgnoreUnknownFields) {
-  TestMessage m;
+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) {
   JsonParseOptions options;
   options.ignore_unknown_fields = true;
-  EXPECT_TRUE(FromJson("{\"unknownName\":0}", &m, options));
-}
+  EXPECT_OK(ToProto<TestMessage>(R"({"unknownName":0})", 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));
+  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_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";
+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);
@@ -363,307 +645,664 @@
   std::unique_ptr<Message> message(
       factory.GetPrototype(pool.FindMessageTypeByName("proto3.TestMessage"))
           ->New());
-  EXPECT_TRUE(FromJson(input, message.get()));
+  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(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));
+  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_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));
+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;
-  EXPECT_TRUE(m.value().UnpackTo(&t));
-  EXPECT_EQ("expected_value", t.string_value());
+  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_F(JsonUtilTest, TestParsingUnknownEnumsProto2) {
-  std::string input =
-      "{\n"
-      "  \"a\": \"UNKNOWN_VALUE\"\n"
-      "}";
-  protobuf_unittest::TestNumbers m;
+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));
+
   JsonParseOptions options;
-  EXPECT_FALSE(FromJson(input, &m, options));
-
   options.ignore_unknown_fields = true;
-  EXPECT_TRUE(FromJson(input, &m, options));
-  EXPECT_FALSE(m.has_a());
+  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_F(JsonUtilTest, TestParsingUnknownEnumsProto3) {
+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));
+
+  JsonParseOptions 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;
-  {
-    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
+  absl::string_view input = R"json({"enum_value":"UNKNOWN_VALUE"})json";
 
-    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());
+  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
 
-    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));
-  }
+  JsonParseOptions 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_F(JsonUtilTest, TestParsingEnumIgnoreCase) {
+TEST_P(JsonTest, TestParsingUnknownEnumsProto3FromInt) {
   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());
-  }
+  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);
+
+  JsonParseOptions options;
+  options.ignore_unknown_fields = true;
+  ASSERT_OK(ToProto(m, input, options));
+  EXPECT_EQ(m.enum_value(), 12345);
 }
 
-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) {}
+// 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";
 
-  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;
-  }
+  EXPECT_THAT(ToProto<TestMessage>(input),
+              StatusIs(absl::StatusCode::kInvalidArgument));
 
-  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));
-    }
-  }
+  JsonParseOptions options;
+  options.ignore_unknown_fields = true;
+  EXPECT_THAT(ToProto<TestMessage>(input, options),
+              StatusIs(absl::StatusCode::kInvalidArgument));
 }
 
-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());
+TEST_P(JsonTest, TestParsingUnknownEnumsProto3FromArray) {
+  absl::string_view input = R"json({"enum_value": []})json";
 
-  auto result_status = util::JsonToBinaryStream(resolver, message_type,
-                                                &input_stream, &output_stream);
+  EXPECT_THAT(ToProto<TestMessage>(input),
+              StatusIs(absl::StatusCode::kInvalidArgument));
 
-  delete resolver;
-
-  EXPECT_FALSE(result_status.ok());
-  EXPECT_TRUE(util::IsInvalidArgument(result_status));
+  JsonParseOptions options;
+  options.ignore_unknown_fields = true;
+  EXPECT_THAT(ToProto<TestMessage>(input, options),
+              StatusIs(absl::StatusCode::kInvalidArgument));
 }
 
-TEST_F(JsonUtilTest, HtmlEscape) {
+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) {
+  JsonParseOptions 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);
+
+  JsonParseOptions 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);
+}
+
+// This functionality is not correctly implemented by the ESF parser, so
+// the test is only turned on when testing json2.
+TEST_P(JsonTest, Extensions) {
+  if (GetParam() == Codec::kResolver || !IsJson2()) {
+    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>");
-  JsonPrintOptions options;
-  EXPECT_EQ("{\"stringValue\":\"\\u003c/script\\u003e\"}", ToJson(m, options));
+  EXPECT_THAT(ToJson(m),
+              IsOkAndHolds(R"({"stringValue":"\u003c/script\u003e"})"));
+
+  proto3::TestEvilJson m2;
+  JsonPrintOptions 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);
+  if (IsJson2()) {
+    EXPECT_EQ(
+        out,
+        R"({"boolValue":true,"int64Value":"3","repeatedInt32Value":[2,2]})");
+  } else {
+    EXPECT_EQ(
+        out,
+        R"({"int64Value":"3","repeatedInt32Value":[2],"boolValue":true,"repeatedInt32Value":[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
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 30560ed..51b2bea 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/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 "absl/container/fixed_array.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/stubs/stringprintf.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,6 +155,10 @@
     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,
                const std::vector<SpecificField>& parent_fields) const override {
     for (const auto& path : key_field_paths_) {
@@ -203,7 +210,6 @@
   }
   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
@@ -337,14 +343,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) {
@@ -1688,6 +1694,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 +1716,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,
@@ -2000,14 +2007,14 @@
         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));
     }
   }
 }
@@ -2072,19 +2079,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());
+          "\"%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 +2133,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..7d1e6ac 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -51,13 +51,14 @@
 #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 "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 +80,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
@@ -238,21 +239,23 @@
   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;
+        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;
+        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 +303,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,6 +310,8 @@
   class PROTOBUF_EXPORT MapKeyComparator {
    public:
     MapKeyComparator();
+    MapKeyComparator(const MapKeyComparator&) = delete;
+    MapKeyComparator& operator=(const MapKeyComparator&) = delete;
     virtual ~MapKeyComparator();
 
     virtual bool IsMatch(
@@ -318,9 +320,6 @@
       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 +353,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();
 
@@ -524,9 +525,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 +649,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 +718,6 @@
     const Message* message1_;
     const Message* message2_;
     MessageDifferencer::UnpackAnyField unpack_any_field_;
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
   };
 
  private:
@@ -952,7 +954,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 +976,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..93a4553 100644
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -39,25 +39,25 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/common.h"
 
-#include <google/protobuf/stubs/strutil.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/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/text_format.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/util/field_comparator.h"
+#include "google/protobuf/util/message_differencer.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/util/message_differencer_unittest.pb.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;
       }
@@ -3472,9 +3472,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..94154a0 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 <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/stubs/strutil.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 "google/protobuf/stubs/stringprintf.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));
@@ -117,15 +136,40 @@
 }
 
 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);
   }
@@ -261,37 +309,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 +370,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 +443,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 +455,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 +483,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 +512,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 +530,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 +546,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..464e57b 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 {
@@ -378,6 +378,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..49ae2d3 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -28,20 +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/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 "google/protobuf/stubs/strutil.h"
+#include "absl/status/status.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/util/internal/utility.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 +71,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,30 +304,30 @@
     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());
@@ -339,7 +340,7 @@
         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..f8e9c19 100644
--- a/src/google/protobuf/util/type_resolver_util.h
+++ b/src/google/protobuf/util/type_resolver_util.h
@@ -42,7 +42,7 @@
 class TypeResolver;
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#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.
@@ -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..d926541 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/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/type_resolver.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/util/json_format_proto3.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..2cc25b5 100644
--- a/src/google/protobuf/well_known_types_unittest.cc
+++ b/src/google/protobuf/well_known_types_unittest.cc
@@ -27,12 +27,12 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#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/stubs/stl_util.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..d9d2913 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -32,30 +32,30 @@
 //  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 "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"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 const size_t kMapEntryTagByteSize = 2;
 
@@ -1765,4 +1765,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..027fcb3 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 "google/protobuf/io/coded_stream.h"
+#include "absl/base/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/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..612ae40 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -32,23 +32,24 @@
 //  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 "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 "absl/strings/str_cat.h"
+#include "google/protobuf/stubs/stringprintf.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -593,8 +594,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 +603,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,
@@ -815,4 +816,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..1af4d06 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/io/coded_stream.h"
+#include "google/protobuf/port.h"
+#include "absl/base/casts.h"
+#include "google/protobuf/arenastring.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..5653be7 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 "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 <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 "google/protobuf/stubs/strutil.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/test_util2.h"
+#include "google/protobuf/stubs/stl_util.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))));
   }
 }
@@ -1706,4 +1706,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..cc9048b 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -5,15 +5,15 @@
 
 #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>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -150,6 +150,8 @@
   ~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_),
@@ -157,6 +159,8 @@
   ~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_),
@@ -164,6 +168,8 @@
   ~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_),
@@ -171,6 +177,8 @@
   ~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_),
@@ -178,6 +186,8 @@
   ~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_),
@@ -185,6 +195,8 @@
   ~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_),
@@ -192,6 +204,8 @@
   ~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_),
@@ -199,6 +213,8 @@
   ~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_),
@@ -206,18 +222,20 @@
   ~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)},
+  { 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[] = {
@@ -246,7 +264,7 @@
   "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;
+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,
     "google/protobuf/wrappers.proto",
@@ -1976,4 +1994,4 @@
 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 cc42a8b..16ec96e 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -1,13 +1,13 @@
 // 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 <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
@@ -19,19 +19,19 @@
 #error regenerate this file with a newer version of protoc.
 #endif
 
-#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/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>
+#include "google/protobuf/port_def.inc"
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fwrappers_2eproto PROTOBUF_EXPORT
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
@@ -191,7 +191,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:
@@ -339,7 +339,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:
@@ -487,7 +487,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:
@@ -635,7 +635,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:
@@ -783,7 +783,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:
@@ -931,7 +931,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:
@@ -1079,7 +1079,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:
@@ -1227,7 +1227,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:
@@ -1380,7 +1380,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:
@@ -1451,7 +1451,7 @@
   return _internal_value();
 }
 inline void DoubleValue::_internal_set_value(double value) {
-  
+
   _impl_.value_ = value;
 }
 inline void DoubleValue::set_value(double value) {
@@ -1475,7 +1475,7 @@
   return _internal_value();
 }
 inline void FloatValue::_internal_set_value(float value) {
-  
+
   _impl_.value_ = value;
 }
 inline void FloatValue::set_value(float value) {
@@ -1499,7 +1499,7 @@
   return _internal_value();
 }
 inline void Int64Value::_internal_set_value(int64_t value) {
-  
+
   _impl_.value_ = value;
 }
 inline void Int64Value::set_value(int64_t value) {
@@ -1523,7 +1523,7 @@
   return _internal_value();
 }
 inline void UInt64Value::_internal_set_value(uint64_t value) {
-  
+
   _impl_.value_ = value;
 }
 inline void UInt64Value::set_value(uint64_t value) {
@@ -1547,7 +1547,7 @@
   return _internal_value();
 }
 inline void Int32Value::_internal_set_value(int32_t value) {
-  
+
   _impl_.value_ = value;
 }
 inline void Int32Value::set_value(int32_t value) {
@@ -1571,7 +1571,7 @@
   return _internal_value();
 }
 inline void UInt32Value::_internal_set_value(uint32_t value) {
-  
+
   _impl_.value_ = value;
 }
 inline void UInt32Value::set_value(uint32_t value) {
@@ -1595,7 +1595,7 @@
   return _internal_value();
 }
 inline void BoolValue::_internal_set_value(bool value) {
-  
+
   _impl_.value_ = value;
 }
 inline void BoolValue::set_value(bool value) {
@@ -1631,11 +1631,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() {
@@ -1644,9 +1644,9 @@
 }
 inline void StringValue::set_allocated_value(std::string* value) {
   if (value != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.value_.SetAllocated(value, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -1685,11 +1685,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() {
@@ -1698,9 +1698,9 @@
 }
 inline void BytesValue::set_allocated_value(std::string* value) {
   if (value != nullptr) {
-    
+
   } else {
-    
+
   }
   _impl_.value_.SetAllocated(value, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -1737,5 +1737,5 @@
 
 // @@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_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto_2epb_2eh
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/utf8_range/BUILD.bazel b/third_party/utf8_range/BUILD.bazel
index 4a8a82b..693f390 100644
--- a/third_party/utf8_range/BUILD.bazel
+++ b/third_party/utf8_range/BUILD.bazel
@@ -1,3 +1,4 @@
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
 
 # Pulled from: https://github.com/cyb70289/utf8
 
@@ -13,7 +14,24 @@
 )
 
 filegroup(
-    name = "cmake_files",
-    srcs = glob(["*"]),
-    visibility = ["//cmake:__pkg__"],
+    name = "all_files",
+    srcs = glob([
+        "*.h",
+        "*.c",
+    ]) + [
+        "BUILD.bazel",
+        "LICENSE",
+    ],
+    visibility = [
+        "//cmake:__pkg__",
+        "//php:__pkg__",
+        "//ruby:__pkg__",
+    ],
+)
+
+pkg_files(
+    name = "dist_files",
+    srcs = [":all_files"],
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//pkg:__pkg__"],
 )
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 0ab9cc0..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
-  # whever 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 ade50a1..4244127 100644
--- a/version.json
+++ b/version.json
@@ -1,17 +1,17 @@
 {
-    "21.x": {
-        "protoc_version": "21.7-dev",
+    "main": {
+        "protoc_version": "22-dev",
         "lts": false,
-        "date": "2022-09-14",
+        "date": "2022-07-21",
         "languages": {
-            "cpp": "3.21.7-dev",
-            "csharp": "3.21.7-dev",
-            "java": "3.21.7-dev",
-            "javascript": "3.21.7-dev",
-            "objectivec": "3.21.7-dev",
-            "php": "3.21.7-dev",
-            "python": "4.21.7-dev",
-            "ruby": "3.21.7-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
+}