diff --git a/.github/workflows/janitor.yml b/.github/workflows/janitor.yml index e6dcc06979..992d4b7113 100644 --- a/.github/workflows/janitor.yml +++ b/.github/workflows/janitor.yml @@ -28,3 +28,47 @@ jobs: echo "Closing #$pr..." gh pr close --comment "Auto-closing Copybara pull request" --delete-branch "$pr" done + + stale-others: + name: Close stale non-copybara PRs and issues + runs-on: ubuntu-latest + steps: + - uses: actions/stale@b69b346013879cedbf50c69f572cd85439a41936 + with: + stale-issue-message: > + We triage inactive PRs and issues in order to make it easier to find + active work. If this issue should remain active or becomes active + again, please add a comment. + + + This issue is labeled `inactive` because the last activity was over + 90 days ago. + close-pr-message: > + We triage inactive PRs and issues in order to make it easier to find + active work. If this issue should remain active or becomes active + again, please reopen it. + + + This issue was closed and archived because there has been no new + activity in the 14 days since the `inactive` label was added. + stale-pr-message: > + We triage inactive PRs and issues in order to make it easier to find + active work. If this PR should remain active, please add a comment. + + + This PR is labeled `inactive` because the last activity was over 90 + days ago. This PR will be closed and archived after 14 additional + days without activity. + close-pr-message: > + We triage inactive PRs and issues in order to make it easier to find + active work. If this PR should remain active or becomes active + again, please reopen it. + + + This PR was closed and archived because there has been no new + activity in the 14 days since the `inactive` label was added. + stale-issue-label: 'inactive' + stale-pr-label: 'inactive' + days-before-stale: 90 + days-before-close: 14 + operations-per-run: 100 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index a6d55589d3..bf2788fe7d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -27,7 +27,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: persist-credentials: false diff --git a/.github/workflows/staleness_check.yml b/.github/workflows/staleness_check.yml index 273a4b0117..2669821443 100644 --- a/.github/workflows/staleness_check.yml +++ b/.github/workflows/staleness_check.yml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - branch: [main, 22.x, 23.x, 24.x] + branch: [main, 22.x, 23.x, 24.x, 25.x] os: [{ name: Linux, value: ubuntu-latest}] name: Test staleness ${{ matrix.os.name }} ${{ github.head_ref && 'PR' || matrix.branch }} @@ -49,10 +49,14 @@ jobs: # In branches where automatic updates work as post-submits, we don't want to run staleness # tests along with user changes. Any stale files will be automatically fixed in a follow-up # commit. - run: | - if [[ -z $COMMIT_TRIGGERED_RUN || -z $MAIN_RUN ]]; then - bazel query 'attr(tags, "staleness_test", //...)' | xargs bazel test $BAZEL_FLAGS || \ - echo "Please run ./regenerate_stale_files.sh to regenerate stale files" - else - bazel query 'attr(tags, "staleness_test", //...)' - fi + uses: protocolbuffers/protobuf-ci/bazel@v2 + with: + credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} + bazel-cache: staleness + bash: > + if [[ -z $COMMIT_TRIGGERED_RUN || -z $MAIN_RUN ]]; then + bazel query 'attr(tags, "staleness_test", //...)' | xargs bazel test $BAZEL_FLAGS || + echo "Please run ./regenerate_stale_files.sh to regenerate stale files"; + else + bazel query 'attr(tags, "staleness_test", //...)'; + fi diff --git a/.github/workflows/staleness_refresh.yml b/.github/workflows/staleness_refresh.yml index c53e4ed9fb..6f6b5ac4b5 100644 --- a/.github/workflows/staleness_refresh.yml +++ b/.github/workflows/staleness_refresh.yml @@ -24,12 +24,16 @@ jobs: fail-fast: false # Don't cancel all jobs if one fails. steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: # Note: this token has an expiration date, so if the workflow starts # failing then you may need to generate a fresh token. token: ${{ secrets.BOT_ACCESS_TOKEN }} - name: Configure name and email address in Git - run: cd ${{ github.workspace }} && git config user.name "Protobuf Team Bot" && git config user.email "protobuf-team-bot@google.com" + run: git config user.name "Protobuf Team Bot" && git config user.email "protobuf-team-bot@google.com" - name: Commit and push update - run: cd ${{ github.workspace }} && ./ci/push_auto_update.sh + uses: protocolbuffers/protobuf-ci/bazel@v2 + with: + credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} + bazel-cache: staleness + bash: ci/push_auto_update.sh diff --git a/.github/workflows/test_cpp.yml b/.github/workflows/test_cpp.yml index 511f9ec189..55c061bc1b 100644 --- a/.github/workflows/test_cpp.yml +++ b/.github/workflows/test_cpp.yml @@ -172,7 +172,7 @@ jobs: image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.13.3-63dd26c0c7a808d92673a3e52e848189d4ab0f17 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- - /install.sh -DCMAKE_CXX_STANDARD=14 ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_USE_EXTERNAL_GTEST=ON -Dprotobuf_ABSL_PROVIDER=package \&\& + /install.sh -DCMAKE_CXX_STANDARD=14 ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_USE_EXTERNAL_GTEST=ON -Dprotobuf_ABSL_PROVIDER=package -Dprotobuf_BUILD_SHARED_LIBS=ON \&\& /test.sh ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON @@ -324,8 +324,8 @@ jobs: # for Apple Silicon to detect issues there. bazel: build --cpu=darwin_arm64 //src/... - name: Windows - os: windows-2019 - cache_key: windows-2019 + os: windows-2022 + cache_key: windows-2022 bazel: test //src/... @com_google_protobuf_examples//... --test_tag_filters=-conformance --build_tag_filters=-conformance name: ${{ matrix.name }} Bazel runs-on: ${{ matrix.os }} @@ -351,14 +351,6 @@ jobs: flags: -DCMAKE_CXX_STANDARD=14 cache-prefix: macos-cmake - name: Windows CMake - os: windows-2019 - flags: >- - -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF - -Dprotobuf_BUILD_SHARED_LIBS=OFF - -Dprotobuf_BUILD_EXAMPLES=ON - vsversion: '2019' - cache-prefix: windows-2019-cmake - - name: Windows CMake 2022 os: windows-2022 flags: >- -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF @@ -366,29 +358,39 @@ jobs: -Dprotobuf_BUILD_EXAMPLES=ON vsversion: '2022' cache-prefix: windows-2022-cmake - - name: Windows CMake 32-bit + - name: Windows CMake 2019 os: windows-2019 flags: >- -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF + -Dprotobuf_BUILD_SHARED_LIBS=OFF + -Dprotobuf_BUILD_EXAMPLES=ON vsversion: '2019' + cache-prefix: windows-2019-cmake + # windows-2019 has python3.7 installed, which is incompatible with the latest gcloud + python-version: '3.8' + - name: Windows CMake 32-bit + os: windows-2022 + flags: >- + -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF + vsversion: '2022' windows-arch: 'win32' - cache-prefix: windows-2019-win32-cmake + cache-prefix: windows-2022-win32-cmake - name: Windows CMake Shared - os: windows-2019 + os: windows-2022 flags: >- -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_SHARED_LIBS=ON - vsversion: '2019' - cache-prefix: windows-2019-cmake + vsversion: '2022' + cache-prefix: windows-2022-cmake - name: Windows CMake Install - os: windows-2019 + os: windows-2022 install-flags: -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_TESTS=OFF flags: >- -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON -Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF - vsversion: '2019' - cache-prefix: windows-2019-cmake + vsversion: '2022' + cache-prefix: windows-2022-cmake name: ${{ matrix.name }} runs-on: ${{ matrix.os }} steps: @@ -405,6 +407,17 @@ jobs: arch: ${{ matrix.windows-arch || 'x64' }} vsversion: ${{ matrix.vsversion }} + # Workaround for incompatibility between gcloud and windows-2019 runners. + - name: Install Python + if: ${{ matrix.python-version }} + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + with: + python-version: ${{ matrix.python-version }} + - name: Use custom python for gcloud + if: ${{ matrix.python-version }} + run: echo "CLOUDSDK_PYTHON=${Python3_ROOT_DIR}\\python3" >> $GITHUB_ENV + shell: bash + - name: Setup sccache uses: protocolbuffers/protobuf-ci/sccache@v2 with: diff --git a/.github/workflows/test_python.yml b/.github/workflows/test_python.yml index e207ee3a92..0bec9a06c3 100644 --- a/.github/workflows/test_python.yml +++ b/.github/workflows/test_python.yml @@ -76,6 +76,7 @@ jobs: with: python-version: ${{ matrix.version }} cache: pip + cache-dependency-path: 'python/requirements.txt' - name: Validate version run: python3 --version | grep ${{ matrix.version }} || (echo "Invalid Python version - $(python3 --version)" && exit 1) diff --git a/.github/workflows/test_runner.yml b/.github/workflows/test_runner.yml index ea84407874..dfd47fbe21 100644 --- a/.github/workflows/test_runner.yml +++ b/.github/workflows/test_runner.yml @@ -12,9 +12,8 @@ name: Tests on: # continuous schedule: - # TODO Reduce this frequency - # Run every 15 minutes for now to gather statistics - - cron: "*/15 * * * *" + # Run every hour + - cron: "0 * * * *" # postsubmit push: diff --git a/.github/workflows/test_upb.yml b/.github/workflows/test_upb.yml index 21ec308876..32b9ff8251 100644 --- a/.github/workflows/test_upb.yml +++ b/.github/workflows/test_upb.yml @@ -64,19 +64,23 @@ jobs: strategy: fail-fast: false # Don't cancel all jobs if one fails. name: Windows - runs-on: windows-2019 + runs-on: windows-2022 steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v2 with: ref: ${{ inputs.safe-checkout }} + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + with: + cache: pip + cache-dependency-path: 'python/requirements.txt' - name: Run tests uses: protocolbuffers/protobuf-ci/bazel@v2 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: "upb-bazel-windows" bazel: test --cxxopt=/std:c++17 --host_cxxopt=/std:c++17 //upb/... //upb_generator/... //python/... //protos/... //protos_generator/... - exclude-targets: -//python:conformance_test -//upb:def_builder_test + exclude-targets: -//python:conformance_test -//upb/reflection:def_builder_test macos: strategy: @@ -92,6 +96,10 @@ jobs: uses: protocolbuffers/protobuf-ci/checkout@v2 with: ref: ${{ inputs.safe-checkout }} + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + with: + cache: pip + cache-dependency-path: 'python/requirements.txt' - name: Run tests uses: protocolbuffers/protobuf-ci/bazel@v2 with: @@ -195,7 +203,7 @@ jobs: with: name: requirements path: requirements - - uses: actions/setup-python@v2 + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.architecture }} @@ -250,7 +258,7 @@ jobs: path: wheels - name: Delete Binary Wheels run: find wheels -type f | grep -v none-any | xargs rm - - uses: actions/setup-python@v2 + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: ${{ matrix.python-version }} - name: Setup Python venv diff --git a/.github/workflows/update_php_repo.yml b/.github/workflows/update_php_repo.yml index cb3383ad01..41ec07626f 100644 --- a/.github/workflows/update_php_repo.yml +++ b/.github/workflows/update_php_repo.yml @@ -15,12 +15,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout protobuf-php - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: repository: protocolbuffers/protobuf-php token: ${{ secrets.BOT_ACCESS_TOKEN }} - name: Clone protobuf - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: path: protobuf - name: Configure Git Bot diff --git a/BUILD.bazel b/BUILD.bazel index 23efee4a31..5951297816 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -224,7 +224,6 @@ alias( cc_library( name = "protobuf", copts = COPTS, - include_prefix = "google/protobuf/io", linkopts = LINK_OPTS, visibility = ["//visibility:public"], deps = [ diff --git a/Cargo.bazel.lock b/Cargo.bazel.lock index 80674909ca..a287466e2e 100644 --- a/Cargo.bazel.lock +++ b/Cargo.bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "8bc2d235f612e77f4dca1b6886cc8bd14df348168fea27a687805ed9518a8f1a", + "checksum": "f93f5d1848bc00c6384273f9fb5273cc1b7fc0cb4dbc2afd776d2feb7b37f3ae", "crates": { "aho-corasick 1.1.2": { "name": "aho-corasick", @@ -108,6 +108,15 @@ "selects": {} }, "edition": "2018", + "proc_macro_deps": { + "common": [ + { + "id": "paste 1.0.14", + "target": "paste" + } + ], + "selects": {} + }, "version": "0.0.1" }, "license": null @@ -318,6 +327,59 @@ }, "license": "MIT OR Apache-2.0" }, + "paste 1.0.14": { + "name": "paste", + "version": "1.0.14", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/paste/1.0.14/download", + "sha256": "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + } + }, + "targets": [ + { + "ProcMacro": { + "crate_name": "paste", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "paste", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "paste 1.0.14", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "1.0.14" + }, + "build_script_attrs": { + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0" + }, "proc-macro2 1.0.69": { "name": "proc-macro2", "version": "1.0.69", @@ -767,6 +829,99 @@ "workspace_members": { "direct-cargo-bazel-deps 0.0.1": "" }, - "conditions": {} + "conditions": { + "aarch64-apple-darwin": [ + "aarch64-apple-darwin" + ], + "aarch64-apple-ios": [ + "aarch64-apple-ios" + ], + "aarch64-apple-ios-sim": [ + "aarch64-apple-ios-sim" + ], + "aarch64-fuchsia": [ + "aarch64-fuchsia" + ], + "aarch64-linux-android": [ + "aarch64-linux-android" + ], + "aarch64-pc-windows-msvc": [ + "aarch64-pc-windows-msvc" + ], + "aarch64-unknown-linux-gnu": [ + "aarch64-unknown-linux-gnu" + ], + "arm-unknown-linux-gnueabi": [ + "arm-unknown-linux-gnueabi" + ], + "armv7-linux-androideabi": [ + "armv7-linux-androideabi" + ], + "armv7-unknown-linux-gnueabi": [ + "armv7-unknown-linux-gnueabi" + ], + "i686-apple-darwin": [ + "i686-apple-darwin" + ], + "i686-linux-android": [ + "i686-linux-android" + ], + "i686-pc-windows-msvc": [ + "i686-pc-windows-msvc" + ], + "i686-unknown-freebsd": [ + "i686-unknown-freebsd" + ], + "i686-unknown-linux-gnu": [ + "i686-unknown-linux-gnu" + ], + "powerpc-unknown-linux-gnu": [ + "powerpc-unknown-linux-gnu" + ], + "riscv32imc-unknown-none-elf": [ + "riscv32imc-unknown-none-elf" + ], + "riscv64gc-unknown-none-elf": [ + "riscv64gc-unknown-none-elf" + ], + "s390x-unknown-linux-gnu": [ + "s390x-unknown-linux-gnu" + ], + "thumbv7em-none-eabi": [ + "thumbv7em-none-eabi" + ], + "thumbv8m.main-none-eabi": [ + "thumbv8m.main-none-eabi" + ], + "wasm32-unknown-unknown": [ + "wasm32-unknown-unknown" + ], + "wasm32-wasi": [ + "wasm32-wasi" + ], + "x86_64-apple-darwin": [ + "x86_64-apple-darwin" + ], + "x86_64-apple-ios": [ + "x86_64-apple-ios" + ], + "x86_64-fuchsia": [ + "x86_64-fuchsia" + ], + "x86_64-linux-android": [ + "x86_64-linux-android" + ], + "x86_64-pc-windows-msvc": [ + "x86_64-pc-windows-msvc" + ], + "x86_64-unknown-freebsd": [ + "x86_64-unknown-freebsd" + ], + "x86_64-unknown-linux-gnu": [ + "x86_64-unknown-linux-gnu" + ], + "x86_64-unknown-none": [ + "x86_64-unknown-none" + ] + } } - diff --git a/Cargo.lock b/Cargo.lock index e075e9722c..ea70571b3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,7 @@ name = "direct-cargo-bazel-deps" version = "0.0.1" dependencies = [ "googletest", + "paste", ] [[package]] @@ -61,6 +62,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "proc-macro2" version = "1.0.69" @@ -130,4 +137,3 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - diff --git a/WORKSPACE b/WORKSPACE index 2c665be1a8..37994f8c06 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -174,8 +174,8 @@ bind( http_archive( name = "rules_rust", - sha256 = "4a9cb4fda6ccd5b5ec393b2e944822a62e050c7c06f1ea41607f14c4fdec57a2", - urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.25.1/rules_rust-v0.25.1.tar.gz"], + sha256 = "9ecd0f2144f0a24e6bc71ebcc50a1ee5128cedeceb32187004532c9710cb2334", + urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.29.1/rules_rust-v0.29.1.tar.gz"], ) load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") @@ -193,6 +193,9 @@ crates_repository( "googletest": crate.spec( version = ">0.0.0", ), + "paste": crate.spec( + version = ">=1", + ), }, ) diff --git a/bazel/BUILD b/bazel/BUILD index b08bf4ecd2..a891d615a2 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -21,7 +21,7 @@ py_binary( ) # py_proto_library() is private rule, only intended for internal use by upb. -# Hopefully py_proto_library() will eventually be availble in rules_proto or +# Hopefully py_proto_library() will eventually be available in rules_proto or # another upstream package. bzl_library( name = "py_proto_library_bzl", diff --git a/benchmarks/BUILD b/benchmarks/BUILD index 07f87a91e7..108eab493f 100644 --- a/benchmarks/BUILD +++ b/benchmarks/BUILD @@ -13,7 +13,7 @@ load("@rules_python//python:defs.bzl", "py_binary") load( "//bazel:upb_proto_library.bzl", - "upb_proto_library", + "upb_c_proto_library", "upb_proto_reflection_library", ) load( @@ -35,7 +35,7 @@ proto_library( srcs = ["descriptor.proto"], ) -upb_proto_library( +upb_c_proto_library( name = "benchmark_descriptor_upb_proto", deps = [":descriptor_proto"], ) @@ -154,7 +154,7 @@ proto_library( ) [( - upb_proto_library( + upb_c_proto_library( name = k + "_upb_proto", deps = [":" + k + "_proto"], ), diff --git a/cmake/conformance.cmake b/cmake/conformance.cmake index 7bebadee1c..bfded7763a 100644 --- a/cmake/conformance.cmake +++ b/cmake/conformance.cmake @@ -33,12 +33,22 @@ add_custom_command( ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.h ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc - DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto - ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto - COMMAND ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto - ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto - --proto_path=${protobuf_SOURCE_DIR}/src - --cpp_out=${protoc_cpp_args}${protobuf_SOURCE_DIR}/src + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.pb.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.pb.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.pb.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.pb.cc + DEPENDS ${protobuf_PROTOC_EXE} + ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto + COMMAND ${protobuf_PROTOC_EXE} + ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto + --proto_path=${protobuf_SOURCE_DIR}/src + --cpp_out=${protoc_cpp_args}${protobuf_SOURCE_DIR}/src ) add_library(libconformance_common ${protobuf_SHARED_OR_STATIC} @@ -48,6 +58,10 @@ add_library(libconformance_common ${protobuf_SHARED_OR_STATIC} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.h ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.pb.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.pb.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.pb.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.pb.cc ) target_link_libraries(libconformance_common ${protobuf_LIB_PROTOBUF} @@ -100,6 +114,7 @@ add_test(NAME conformance_cpp_test --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} + --maximum_edition 2023 ${CMAKE_CURRENT_BINARY_DIR}/conformance_cpp DEPENDS conformance_test_runner conformance_cpp) diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 489ca65c2a..044af4835f 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -62,6 +62,7 @@ set(tests_files ${protobuf_test_files} ${compiler_test_files} ${annotation_test_util_srcs} + ${editions_test_files} ${io_test_files} ${util_test_files} ${stubs_test_files} diff --git a/conformance/BUILD.bazel b/conformance/BUILD.bazel index c4955042cb..e54eab02d2 100644 --- a/conformance/BUILD.bazel +++ b/conformance/BUILD.bazel @@ -130,6 +130,7 @@ internal_ruby_proto_library( cc_library( name = "conformance_test", + testonly = 1, srcs = [ "conformance_test.cc", "conformance_test_runner.cc", @@ -151,12 +152,16 @@ cc_library( cc_library( name = "binary_json_conformance_suite", + testonly = 1, srcs = ["binary_json_conformance_suite.cc"], hdrs = ["binary_json_conformance_suite.h"], deps = [ ":conformance_test", ":test_messages_proto2_proto_cc", ":test_messages_proto3_proto_cc", + "//src/google/protobuf/editions:test_messages_proto2_editions_cc_proto", + "//src/google/protobuf/editions:test_messages_proto3_editions_cc_proto", + "@com_google_absl//absl/log:die_if_null", "@com_google_absl//absl/status", "@jsoncpp", ], @@ -164,17 +169,24 @@ cc_library( cc_library( name = "text_format_conformance_suite", + testonly = 1, srcs = ["text_format_conformance_suite.cc"], hdrs = ["text_format_conformance_suite.h"], deps = [ ":conformance_test", ":test_messages_proto2_proto_cc", ":test_messages_proto3_proto_cc", + "//src/google/protobuf/editions:test_messages_proto2_editions_cc_proto", + "//src/google/protobuf/editions:test_messages_proto3_editions_cc_proto", + "@com_google_absl//absl/log:absl_log", + "@com_google_absl//absl/log:die_if_null", + "@com_google_absl//absl/strings", ], ) cc_binary( name = "conformance_test_runner", + testonly = 1, srcs = ["conformance_test_main.cc"], visibility = ["//visibility:public"], deps = [ @@ -195,6 +207,8 @@ cc_binary( "//:protobuf", "//:test_messages_proto2_cc_proto", "//:test_messages_proto3_cc_proto", + "//src/google/protobuf/editions:test_messages_proto2_editions_cc_proto", + "//src/google/protobuf/editions:test_messages_proto3_editions_cc_proto", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", ], diff --git a/conformance/bazel_conformance_test_runner.sh b/conformance/bazel_conformance_test_runner.sh index fcf4a485b7..c434c1fcdc 100755 --- a/conformance/bazel_conformance_test_runner.sh +++ b/conformance/bazel_conformance_test_runner.sh @@ -28,9 +28,10 @@ else fi # --- end runfiles.bash initialization --- -TESTEE=unset -FAILURE_LIST=unset -TEXT_FORMAT_FAILURE_LIST=unset +TESTEE= +FAILURE_LIST= +TEXT_FORMAT_FAILURE_LIST= +MAXIMUM_EDITION= while [[ -n "$@" ]]; do arg="$1"; shift @@ -39,6 +40,7 @@ while [[ -n "$@" ]]; do "--testee") TESTEE="$val" ;; "--failure_list") FAILURE_LIST="$val" ;; "--text_format_failure_list") TEXT_FORMAT_FAILURE_LIST="$val" ;; + "--maximum_edition") MAXIMUM_EDITION="$val" ;; *) echo "Flag $arg is not recognized." && exit 1 ;; esac done @@ -57,4 +59,8 @@ if [ -n "$text_format_failure_list" ]; then args+=(--text_format_failure_list $text_format_failure_list) fi +if [ -n "$MAXIMUM_EDITION" ]; then + args+=(--maximum_edition $MAXIMUM_EDITION) +fi + $conformance_test_runner "${args[@]}" $conformance_testee diff --git a/conformance/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc index cc43c86589..628afdcb8a 100644 --- a/conformance/binary_json_conformance_suite.cc +++ b/conformance/binary_json_conformance_suite.cc @@ -7,40 +7,53 @@ #include "binary_json_conformance_suite.h" +#include +#include +#include +#include +#include #include #include +#include #include #include -#include "google/protobuf/util/json_util.h" -#include "google/protobuf/util/type_resolver_util.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" +#include "absl/log/die_if_null.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "absl/strings/substitute.h" #include "json/json.h" #include "conformance/conformance.pb.h" #include "conformance_test.h" +#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h" +#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h" #include "google/protobuf/endian.h" +#include "google/protobuf/json/json.h" +#include "google/protobuf/test_messages_proto2.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/text_format.h" +#include "google/protobuf/util/type_resolver_util.h" #include "google/protobuf/wire_format_lite.h" -namespace proto2_messages = protobuf_test_messages::proto2; - using conformance::ConformanceRequest; using conformance::ConformanceResponse; using conformance::WireFormat; using google::protobuf::Descriptor; using google::protobuf::FieldDescriptor; -using google::protobuf::Message; using google::protobuf::internal::WireFormatLite; using google::protobuf::internal::little_endian::FromHost; using google::protobuf::util::NewTypeResolverForDescriptorPool; -using proto2_messages::TestAllTypesProto2; +using protobuf_test_messages::proto2::TestAllTypesProto2; using protobuf_test_messages::proto3::TestAllTypesProto3; -using std::string; +using TestAllTypesProto2Editions = + protobuf_test_messages::editions::proto2::TestAllTypesProto2; +using TestAllTypesProto3Editions = + protobuf_test_messages::editions::proto3::TestAllTypesProto3; namespace { @@ -50,7 +63,7 @@ constexpr absl::string_view kTypeUrlPrefix = "type.googleapis.com"; // Corresponds approx to 500KB wireformat bytes. const size_t kPerformanceRepeatCount = 50000; -string GetTypeUrl(const Descriptor* message) { +std::string GetTypeUrl(const Descriptor* message) { return absl::StrCat(kTypeUrlPrefix, "/", message->full_name()); } @@ -82,52 +95,56 @@ size_t vencode64(uint64_t val, int over_encoded_bytes, char* buf) { return i; } -string varint(uint64_t x) { +std::string varint(uint64_t x) { char buf[VARINT_MAX_LEN]; size_t len = vencode64(x, 0, buf); - return string(buf, len); + return std::string(buf, len); } // Encodes a varint that is |extra| bytes longer than it needs to be, but still // valid. -string longvarint(uint64_t x, int extra) { +std::string longvarint(uint64_t x, int extra) { char buf[VARINT_MAX_LEN]; size_t len = vencode64(x, extra, buf); - return string(buf, len); + return std::string(buf, len); } -string fixed32(void* data) { +std::string fixed32(void* data) { uint32_t data_le; std::memcpy(&data_le, data, 4); data_le = FromHost(data_le); - return string(reinterpret_cast(&data_le), 4); + return std::string(reinterpret_cast(&data_le), 4); } -string fixed64(void* data) { +std::string fixed64(void* data) { uint64_t data_le; std::memcpy(&data_le, data, 8); data_le = FromHost(data_le); - return string(reinterpret_cast(&data_le), 8); + return std::string(reinterpret_cast(&data_le), 8); } -string delim(const string& buf) { +std::string delim(const std::string& buf) { return absl::StrCat(varint(buf.size()), buf); } -string u32(uint32_t u32) { return fixed32(&u32); } -string u64(uint64_t u64) { return fixed64(&u64); } -string flt(float f) { return fixed32(&f); } -string dbl(double d) { return fixed64(&d); } -string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); } -string zz64(int64_t x) { return varint(WireFormatLite::ZigZagEncode64(x)); } +std::string u32(uint32_t u32) { return fixed32(&u32); } +std::string u64(uint64_t u64) { return fixed64(&u64); } +std::string flt(float f) { return fixed32(&f); } +std::string dbl(double d) { return fixed64(&d); } +std::string zz32(int32_t x) { + return varint(WireFormatLite::ZigZagEncode32(x)); +} +std::string zz64(int64_t x) { + return varint(WireFormatLite::ZigZagEncode64(x)); +} -string tag(uint32_t fieldnum, char wire_type) { +std::string tag(uint32_t fieldnum, char wire_type) { return varint((fieldnum << 3) | wire_type); } -string tag(int fieldnum, char wire_type) { +std::string tag(int fieldnum, char wire_type) { return tag(static_cast(fieldnum), wire_type); } -string GetDefaultValue(FieldDescriptor::Type type) { +std::string GetDefaultValue(FieldDescriptor::Type type) { switch (type) { case FieldDescriptor::TYPE_INT32: case FieldDescriptor::TYPE_INT64: @@ -160,7 +177,7 @@ string GetDefaultValue(FieldDescriptor::Type type) { return ""; } -string GetNonDefaultValue(FieldDescriptor::Type type) { +std::string GetNonDefaultValue(FieldDescriptor::Type type) { switch (type) { case FieldDescriptor::TYPE_INT32: case FieldDescriptor::TYPE_INT64: @@ -197,105 +214,15 @@ string GetNonDefaultValue(FieldDescriptor::Type type) { #define UNKNOWN_FIELD 666 -enum class Packed { - kUnspecified = 0, - kTrue = 1, - kFalse = 2, -}; - -const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type, - bool repeated, bool is_proto3, - Packed packed = Packed::kUnspecified) { - const Descriptor* d = is_proto3 ? TestAllTypesProto3().GetDescriptor() - : TestAllTypesProto2().GetDescriptor(); - for (int i = 0; i < d->field_count(); i++) { - const FieldDescriptor* f = d->field(i); - if (f->type() == type && f->is_repeated() == repeated) { - if ((packed == Packed::kTrue && !f->is_packed()) || - (packed == Packed::kFalse && f->is_packed())) { - continue; - } - return f; - } - } - - absl::string_view packed_string = ""; - const absl::string_view repeated_string = - repeated ? "Repeated " : "Singular "; - const absl::string_view proto_string = is_proto3 ? "Proto3" : "Proto2"; - if (packed == Packed::kTrue) { - packed_string = "Packed "; - } - if (packed == Packed::kFalse) { - packed_string = "Unpacked "; - } - ABSL_LOG(FATAL) << "Couldn't find field with type: " << repeated_string - << packed_string << FieldDescriptor::TypeName(type) << " for " - << proto_string; - return nullptr; -} - -const FieldDescriptor* GetFieldForMapType(FieldDescriptor::Type key_type, - FieldDescriptor::Type value_type, - bool is_proto3) { - const Descriptor* d = is_proto3 ? TestAllTypesProto3().GetDescriptor() - : TestAllTypesProto2().GetDescriptor(); - for (int i = 0; i < d->field_count(); i++) { - const FieldDescriptor* f = d->field(i); - if (f->is_map()) { - const Descriptor* map_entry = f->message_type(); - const FieldDescriptor* key = map_entry->field(0); - const FieldDescriptor* value = map_entry->field(1); - if (key->type() == key_type && value->type() == value_type) { - return f; - } - } - } - - const absl::string_view proto_string = is_proto3 ? "Proto3" : "Proto2"; - ABSL_LOG(FATAL) << "Couldn't find map field with type: " - << FieldDescriptor::TypeName(key_type) << " and " - << FieldDescriptor::TypeName(key_type) << " for " - << proto_string; - return nullptr; -} - -const FieldDescriptor* GetFieldForOneofType(FieldDescriptor::Type type, - bool is_proto3, - bool exclusive = false) { - const Descriptor* d = is_proto3 ? TestAllTypesProto3().GetDescriptor() - : TestAllTypesProto2().GetDescriptor(); - for (int i = 0; i < d->field_count(); i++) { - const FieldDescriptor* f = d->field(i); - if (f->containing_oneof() && ((f->type() == type) ^ exclusive)) { - return f; - } - } - - const absl::string_view proto_string = is_proto3 ? "Proto3" : "Proto2"; - ABSL_LOG(FATAL) << "Couldn't find oneof field with type: " - << FieldDescriptor::TypeName(type) << " for " << proto_string; - return nullptr; -} - -string UpperCase(string str) { +std::string UpperCase(std::string str) { for (size_t i = 0; i < str.size(); i++) { str[i] = toupper(str[i]); } return str; } -std::unique_ptr NewTestMessage(bool is_proto3) { - std::unique_ptr prototype; - if (is_proto3) { - prototype = std::make_unique(); - } else { - prototype = std::make_unique(); - } - return prototype; -} - -bool IsProto3Default(FieldDescriptor::Type type, const string& binary_data) { +bool IsProto3Default(FieldDescriptor::Type type, + const std::string& binary_data) { switch (type) { case FieldDescriptor::TYPE_DOUBLE: return binary_data == dbl(0); @@ -331,10 +258,10 @@ namespace protobuf { bool BinaryAndJsonConformanceSuite::ParseJsonResponse( const ConformanceResponse& response, Message* test_message) { - string binary_protobuf; + std::string binary_protobuf; absl::Status status = - JsonToBinaryString(type_resolver_.get(), type_url_, - response.json_payload(), &binary_protobuf); + json::JsonToBinaryString(type_resolver_.get(), type_url_, + response.json_payload(), &binary_protobuf); if (!status.ok()) { return false; @@ -354,7 +281,7 @@ bool BinaryAndJsonConformanceSuite::ParseResponse( const ConformanceRequestSetting& setting, Message* test_message) { const ConformanceRequest& request = setting.GetRequest(); WireFormat requested_output = request.requested_output_format(); - const string& test_name = setting.GetTestName(); + const std::string& test_name = setting.GetTestName(); ConformanceLevel level = setting.GetLevel(); switch (response.result_case()) { @@ -402,38 +329,57 @@ bool BinaryAndJsonConformanceSuite::ParseResponse( return true; } -void BinaryAndJsonConformanceSuite::ExpectParseFailureForProtoWithProtoVersion( - const string& proto, const string& test_name, ConformanceLevel level, - bool is_proto3) { - std::unique_ptr prototype = NewTestMessage(is_proto3); +void BinaryAndJsonConformanceSuite::RunSuiteImpl() { + type_resolver_.reset(NewTypeResolverForDescriptorPool( + kTypeUrlPrefix, DescriptorPool::generated_pool())); + + BinaryAndJsonConformanceSuiteImpl( + this, /*run_proto3_tests=*/true); + BinaryAndJsonConformanceSuiteImpl( + this, /*run_proto3_tests=*/false); + if (maximum_edition_ >= Edition::EDITION_2023) { + BinaryAndJsonConformanceSuiteImpl( + this, /*run_proto3_tests=*/true); + BinaryAndJsonConformanceSuiteImpl( + this, /*run_proto3_tests=*/false); + } +} + +template +void BinaryAndJsonConformanceSuiteImpl:: + ExpectParseFailureForProtoWithProtoVersion(const std::string& proto, + const std::string& test_name, + ConformanceLevel level) { + MessageType prototype; // We don't expect output, but if the program erroneously accepts the protobuf // we let it send its response as this. We must not leave it unspecified. ConformanceRequestSetting setting( level, conformance::PROTOBUF, conformance::PROTOBUF, - conformance::BINARY_TEST, *prototype, test_name, proto); + conformance::BINARY_TEST, prototype, test_name, proto); const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; - string effective_test_name = absl::StrCat( - setting.ConformanceLevelToString(level), - (is_proto3 ? ".Proto3" : ".Proto2"), ".ProtobufInput.", test_name); + std::string effective_test_name = + absl::StrCat(setting.ConformanceLevelToString(level), ".", + setting.GetSyntaxIdentifier(), ".ProtobufInput.", test_name); - RunTest(effective_test_name, request, &response); + suite_.RunTest(effective_test_name, request, &response); if (response.result_case() == ConformanceResponse::kParseError) { - ReportSuccess(effective_test_name); + suite_.ReportSuccess(effective_test_name); } else if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(effective_test_name, request, response); } else { - ReportFailure(effective_test_name, level, request, response, - "Should have failed to parse, but didn't."); + suite_.ReportFailure(effective_test_name, level, request, response, + "Should have failed to parse, but didn't."); } } // Expect that this precise protobuf will cause a parse error. -void BinaryAndJsonConformanceSuite::ExpectParseFailureForProto( - const string& proto, const string& test_name, ConformanceLevel level) { - ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, true); - ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, false); +template +void BinaryAndJsonConformanceSuiteImpl::ExpectParseFailureForProto( + const std::string& proto, const std::string& test_name, + ConformanceLevel level) { + ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level); } // Expect that this protobuf will cause a parse error, even if it is followed @@ -441,180 +387,191 @@ void BinaryAndJsonConformanceSuite::ExpectParseFailureForProto( // data verbatim and once with this data followed by some valid data. // // TODO: implement the second of these. -void BinaryAndJsonConformanceSuite::ExpectHardParseFailureForProto( - const string& proto, const string& test_name, ConformanceLevel level) { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::ExpectHardParseFailureForProto(const std::string& proto, + const std::string& test_name, + ConformanceLevel level) { return ExpectParseFailureForProto(proto, test_name, level); } -void BinaryAndJsonConformanceSuite::RunValidJsonTest( - const string& test_name, ConformanceLevel level, const string& input_json, - const string& equivalent_text_format) { - TestAllTypesProto3 prototype; +template +void BinaryAndJsonConformanceSuiteImpl::RunValidJsonTest( + const std::string& test_name, ConformanceLevel level, + const std::string& input_json, const std::string& equivalent_text_format) { + MessageType prototype; RunValidJsonTestWithMessage(test_name, level, input_json, equivalent_text_format, prototype); } -void BinaryAndJsonConformanceSuite::RunValidJsonTest( - const string& test_name, ConformanceLevel level, const string& input_json, - const string& equivalent_text_format, bool is_proto3) { - if (is_proto3) { - RunValidJsonTest(test_name, level, input_json, equivalent_text_format); - } else { - TestAllTypesProto2 prototype; - RunValidJsonTestWithMessage(test_name, level, input_json, - equivalent_text_format, prototype); - } -} - -void BinaryAndJsonConformanceSuite::RunValidJsonTestWithMessage( - const string& test_name, ConformanceLevel level, const string& input_json, - const string& equivalent_text_format, const Message& prototype) { +template +void BinaryAndJsonConformanceSuiteImpl:: + RunValidJsonTestWithMessage(const std::string& test_name, + ConformanceLevel level, + const std::string& input_json, + const std::string& equivalent_text_format, + const Message& prototype) { ConformanceRequestSetting setting1( level, conformance::JSON, conformance::PROTOBUF, conformance::JSON_TEST, prototype, test_name, input_json); - RunValidInputTest(setting1, equivalent_text_format); + suite_.RunValidInputTest(setting1, equivalent_text_format); ConformanceRequestSetting setting2(level, conformance::JSON, conformance::JSON, conformance::JSON_TEST, prototype, test_name, input_json); - RunValidInputTest(setting2, equivalent_text_format); + suite_.RunValidInputTest(setting2, equivalent_text_format); } -void BinaryAndJsonConformanceSuite::RunValidJsonTestWithProtobufInput( - const string& test_name, ConformanceLevel level, - const TestAllTypesProto3& input, const string& equivalent_text_format) { +template +void BinaryAndJsonConformanceSuiteImpl:: + RunValidJsonTestWithProtobufInput( + const std::string& test_name, ConformanceLevel level, + const MessageType& input, const std::string& equivalent_text_format) { ConformanceRequestSetting setting( level, conformance::PROTOBUF, conformance::JSON, conformance::JSON_TEST, input, test_name, input.SerializeAsString()); - RunValidInputTest(setting, equivalent_text_format); + suite_.RunValidInputTest(setting, equivalent_text_format); } -void BinaryAndJsonConformanceSuite::RunValidJsonIgnoreUnknownTest( - const string& test_name, ConformanceLevel level, const string& input_json, - const string& equivalent_text_format) { - TestAllTypesProto3 prototype; +template +void BinaryAndJsonConformanceSuiteImpl:: + RunValidJsonIgnoreUnknownTest(const std::string& test_name, + ConformanceLevel level, + const std::string& input_json, + const std::string& equivalent_text_format) { + MessageType prototype; ConformanceRequestSetting setting( level, conformance::JSON, conformance::PROTOBUF, conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST, prototype, test_name, input_json); - RunValidInputTest(setting, equivalent_text_format); + suite_.RunValidInputTest(setting, equivalent_text_format); } -void BinaryAndJsonConformanceSuite::RunValidProtobufTest( - const string& test_name, ConformanceLevel level, - const string& input_protobuf, const string& equivalent_text_format, - bool is_proto3) { - std::unique_ptr prototype = NewTestMessage(is_proto3); +template +void BinaryAndJsonConformanceSuiteImpl::RunValidProtobufTest( + const std::string& test_name, ConformanceLevel level, + const std::string& input_protobuf, + const std::string& equivalent_text_format) { + MessageType prototype; ConformanceRequestSetting setting1( level, conformance::PROTOBUF, conformance::PROTOBUF, - conformance::BINARY_TEST, *prototype, test_name, input_protobuf); - RunValidInputTest(setting1, equivalent_text_format); + conformance::BINARY_TEST, prototype, test_name, input_protobuf); + suite_.RunValidInputTest(setting1, equivalent_text_format); - if (is_proto3) { + if (run_proto3_tests_) { ConformanceRequestSetting setting2( level, conformance::PROTOBUF, conformance::JSON, - conformance::BINARY_TEST, *prototype, test_name, input_protobuf); - RunValidInputTest(setting2, equivalent_text_format); + conformance::BINARY_TEST, prototype, test_name, input_protobuf); + suite_.RunValidInputTest(setting2, equivalent_text_format); } } -void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest( - const string& test_name, ConformanceLevel level, - const string& input_protobuf, bool is_proto3) { - RunValidBinaryProtobufTest(test_name, level, input_protobuf, input_protobuf, - is_proto3); +template +void BinaryAndJsonConformanceSuiteImpl::RunValidBinaryProtobufTest( + const std::string& test_name, ConformanceLevel level, + const std::string& input_protobuf) { + RunValidBinaryProtobufTest(test_name, level, input_protobuf, input_protobuf); } -void BinaryAndJsonConformanceSuite::RunValidBinaryProtobufTest( - const string& test_name, ConformanceLevel level, - const string& input_protobuf, const string& expected_protobuf, - bool is_proto3) { - std::unique_ptr prototype = NewTestMessage(is_proto3); +template +void BinaryAndJsonConformanceSuiteImpl::RunValidBinaryProtobufTest( + const std::string& test_name, ConformanceLevel level, + const std::string& input_protobuf, const std::string& expected_protobuf) { + MessageType prototype; ConformanceRequestSetting setting( level, conformance::PROTOBUF, conformance::PROTOBUF, - conformance::BINARY_TEST, *prototype, test_name, input_protobuf); - RunValidBinaryInputTest(setting, expected_protobuf, true); + conformance::BINARY_TEST, prototype, test_name, input_protobuf); + suite_.RunValidBinaryInputTest(setting, expected_protobuf, true); } -void BinaryAndJsonConformanceSuite::RunBinaryPerformanceMergeMessageWithField( - const string& test_name, const string& field_proto, bool is_proto3) { - string message_tag = tag(27, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - string message_proto = absl::StrCat(message_tag, delim(field_proto)); +template +void BinaryAndJsonConformanceSuiteImpl:: + RunBinaryPerformanceMergeMessageWithField(const std::string& test_name, + const std::string& field_proto) { + std::string message_tag = tag(27, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + std::string message_proto = absl::StrCat(message_tag, delim(field_proto)); - string proto; + std::string proto; for (size_t i = 0; i < kPerformanceRepeatCount; i++) { proto.append(message_proto); } - string multiple_repeated_field_proto; + std::string multiple_repeated_field_proto; for (size_t i = 0; i < kPerformanceRepeatCount; i++) { multiple_repeated_field_proto.append(field_proto); } - string expected_proto = + std::string expected_proto = absl::StrCat(message_tag, delim(multiple_repeated_field_proto)); - RunValidBinaryProtobufTest(test_name, RECOMMENDED, proto, expected_proto, - is_proto3); + RunValidBinaryProtobufTest(test_name, RECOMMENDED, proto, expected_proto); } -void BinaryAndJsonConformanceSuite::RunValidProtobufTestWithMessage( - const string& test_name, ConformanceLevel level, const Message* input, - const string& equivalent_text_format, bool is_proto3) { +template +void BinaryAndJsonConformanceSuiteImpl:: + RunValidProtobufTestWithMessage(const std::string& test_name, + ConformanceLevel level, + const Message* input, + const std::string& equivalent_text_format) { RunValidProtobufTest(test_name, level, input->SerializeAsString(), - equivalent_text_format, is_proto3); + equivalent_text_format); } // According to proto JSON specification, JSON serializers follow more strict // rules than parsers (e.g., a serializer must serialize int32 values as JSON // numbers while the parser is allowed to accept them as JSON strings). This // method allows strict checking on a proto JSON serializer by inspecting -// the JSON output directly. -void BinaryAndJsonConformanceSuite::RunValidJsonTestWithValidator( - const string& test_name, ConformanceLevel level, const string& input_json, - const Validator& validator, bool is_proto3) { - std::unique_ptr prototype = NewTestMessage(is_proto3); + +template // the JSON output directly. +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunValidJsonTestWithValidator(const std::string& test_name, + ConformanceLevel level, + const std::string& input_json, + const Validator& validator) { + MessageType prototype; ConformanceRequestSetting setting(level, conformance::JSON, conformance::JSON, - conformance::JSON_TEST, *prototype, + conformance::JSON_TEST, prototype, test_name, input_json); const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; - string effective_test_name = - absl::StrCat(setting.ConformanceLevelToString(level), - is_proto3 ? ".Proto3.JsonInput." : ".Proto2.JsonInput.", - test_name, ".Validator"); + std::string effective_test_name = absl::StrCat( + setting.ConformanceLevelToString(level), ".", + setting.GetSyntaxIdentifier(), ".JsonInput.", test_name, ".Validator"); - RunTest(effective_test_name, request, &response); + suite_.RunTest(effective_test_name, request, &response); if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(effective_test_name, request, response); return; } if (response.result_case() != ConformanceResponse::kJsonPayload) { - ReportFailure(effective_test_name, level, request, response, - absl::StrCat("Expected JSON payload but got type ", - response.result_case())); + suite_.ReportFailure(effective_test_name, level, request, response, + absl::StrCat("Expected JSON payload but got type ", + response.result_case())); return; } Json::Reader reader; Json::Value value; if (!reader.parse(response.json_payload(), value)) { - ReportFailure(effective_test_name, level, request, response, - absl::StrCat("JSON payload cannot be parsed as valid JSON: ", - reader.getFormattedErrorMessages())); + suite_.ReportFailure( + effective_test_name, level, request, response, + absl::StrCat("JSON payload cannot be parsed as valid JSON: ", + reader.getFormattedErrorMessages())); return; } if (!validator(value)) { - ReportFailure(effective_test_name, level, request, response, - "JSON payload validation failed."); + suite_.ReportFailure(effective_test_name, level, request, response, + "JSON payload validation failed."); return; } - ReportSuccess(effective_test_name); + suite_.ReportSuccess(effective_test_name); } -void BinaryAndJsonConformanceSuite::ExpectParseFailureForJson( - const string& test_name, ConformanceLevel level, const string& input_json) { - TestAllTypesProto3 prototype; +template +void BinaryAndJsonConformanceSuiteImpl::ExpectParseFailureForJson( + const std::string& test_name, ConformanceLevel level, + const std::string& input_json) { + MessageType prototype; // We don't expect output, but if the program erroneously accepts the protobuf // we let it send its response as this. We must not leave it unspecified. ConformanceRequestSetting setting(level, conformance::JSON, conformance::JSON, @@ -622,48 +579,53 @@ void BinaryAndJsonConformanceSuite::ExpectParseFailureForJson( test_name, input_json); const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; - string effective_test_name = absl::StrCat( - setting.ConformanceLevelToString(level), ".Proto3.JsonInput.", test_name); + std::string effective_test_name = + absl::StrCat(setting.ConformanceLevelToString(level), ".", + SyntaxIdentifier(), ".JsonInput.", test_name); - RunTest(effective_test_name, request, &response); + suite_.RunTest(effective_test_name, request, &response); if (response.result_case() == ConformanceResponse::kParseError) { - ReportSuccess(effective_test_name); + suite_.ReportSuccess(effective_test_name); } else if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(effective_test_name, request, response); } else { - ReportFailure(effective_test_name, level, request, response, - "Should have failed to parse, but didn't."); + suite_.ReportFailure(effective_test_name, level, request, response, + "Should have failed to parse, but didn't."); } } -void BinaryAndJsonConformanceSuite::ExpectSerializeFailureForJson( - const string& test_name, ConformanceLevel level, - const string& text_format) { - TestAllTypesProto3 payload_message; +template +void BinaryAndJsonConformanceSuiteImpl:: + ExpectSerializeFailureForJson(const std::string& test_name, + ConformanceLevel level, + const std::string& text_format) { + MessageType payload_message; ABSL_CHECK(TextFormat::ParseFromString(text_format, &payload_message)) << "Failed to parse: " << text_format; - TestAllTypesProto3 prototype; + MessageType prototype; ConformanceRequestSetting setting( level, conformance::PROTOBUF, conformance::JSON, conformance::JSON_TEST, prototype, test_name, payload_message.SerializeAsString()); const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; - string effective_test_name = absl::StrCat( - setting.ConformanceLevelToString(level), ".", test_name, ".JsonOutput"); + std::string effective_test_name = + absl::StrCat(setting.ConformanceLevelToString(level), ".", + SyntaxIdentifier(), ".", test_name, ".JsonOutput"); - RunTest(effective_test_name, request, &response); + suite_.RunTest(effective_test_name, request, &response); if (response.result_case() == ConformanceResponse::kSerializeError) { - ReportSuccess(effective_test_name); + suite_.ReportSuccess(effective_test_name); } else if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(effective_test_name, request, response); } else { - ReportFailure(effective_test_name, level, request, response, - "Should have failed to serialize, but didn't."); + suite_.ReportFailure(effective_test_name, level, request, response, + "Should have failed to serialize, but didn't."); } } -void BinaryAndJsonConformanceSuite::TestPrematureEOFForType( +template +void BinaryAndJsonConformanceSuiteImpl::TestPrematureEOFForType( FieldDescriptor::Type type) { // Incomplete values for each wire type. static constexpr absl::string_view incompletes[6] = { @@ -675,12 +637,12 @@ void BinaryAndJsonConformanceSuite::TestPrematureEOFForType( "abc" // 32BIT }; - const FieldDescriptor* field = GetFieldForType(type, false, true); - const FieldDescriptor* rep_field = GetFieldForType(type, true, true); + const FieldDescriptor* field = GetFieldForType(type, false); + const FieldDescriptor* rep_field = GetFieldForType(type, true); WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( static_cast(type)); absl::string_view incomplete = incompletes[wire_type]; - const string type_name = + const std::string type_name = UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type))); ExpectParseFailureForProto( @@ -732,7 +694,7 @@ void BinaryAndJsonConformanceSuite::TestPrematureEOFForType( if (type == FieldDescriptor::TYPE_MESSAGE) { // Submessage ends in the middle of a value. - string incomplete_submsg = absl::StrCat( + std::string incomplete_submsg = absl::StrCat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT), incompletes[WireFormatLite::WIRETYPE_VARINT]); ExpectHardParseFailureForProto( @@ -760,175 +722,174 @@ void BinaryAndJsonConformanceSuite::TestPrematureEOFForType( } } -void BinaryAndJsonConformanceSuite::TestValidDataForType( +template +void BinaryAndJsonConformanceSuiteImpl::TestValidDataForType( FieldDescriptor::Type type, std::vector> values) { - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - const string type_name = - UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type))); - WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( - static_cast(type)); - const FieldDescriptor* field = GetFieldForType(type, false, is_proto3); - const FieldDescriptor* rep_field = GetFieldForType(type, true, is_proto3); - - // Test singular data for singular fields. - for (size_t i = 0; i < values.size(); i++) { - string proto = - absl::StrCat(tag(field->number(), wire_type), values[i].first); - // In proto3, default primitive fields should not be encoded. - string expected_proto = - is_proto3 && IsProto3Default(field->type(), values[i].second) - ? "" - : absl::StrCat(tag(field->number(), wire_type), values[i].second); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(expected_proto); - string text; - TextFormat::PrintToString(*test_message, &text); - - RunValidProtobufTest( - absl::StrCat("ValidDataScalar", type_name, "[", i, "]"), REQUIRED, - proto, text, is_proto3); - RunValidBinaryProtobufTest( - absl::StrCat("ValidDataScalarBinary", type_name, "[", i, "]"), - RECOMMENDED, proto, expected_proto, is_proto3); - } + const std::string type_name = + UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type))); + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast(type)); + const FieldDescriptor* field = GetFieldForType(type, false); + const FieldDescriptor* rep_field = GetFieldForType(type, true); + + // Test singular data for singular fields. + for (size_t i = 0; i < values.size(); i++) { + std::string proto = + absl::StrCat(tag(field->number(), wire_type), values[i].first); + // In proto3, default primitive fields should not be encoded. + std::string expected_proto = + run_proto3_tests_ && IsProto3Default(field->type(), values[i].second) + ? "" + : absl::StrCat(tag(field->number(), wire_type), values[i].second); + MessageType test_message; + test_message.MergeFromString(expected_proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + + RunValidProtobufTest( + absl::StrCat("ValidDataScalar", type_name, "[", i, "]"), REQUIRED, + proto, text); + RunValidBinaryProtobufTest( + absl::StrCat("ValidDataScalarBinary", type_name, "[", i, "]"), + RECOMMENDED, proto, expected_proto); + } - // Test repeated data for singular fields. - // For scalar message fields, repeated values are merged, which is tested - // separately. - if (type != FieldDescriptor::TYPE_MESSAGE) { - string proto; - for (size_t i = 0; i < values.size(); i++) { - proto += absl::StrCat(tag(field->number(), wire_type), values[i].first); - } - string expected_proto = - absl::StrCat(tag(field->number(), wire_type), values.back().second); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(expected_proto); - string text; - TextFormat::PrintToString(*test_message, &text); - - RunValidProtobufTest(absl::StrCat("RepeatedScalarSelectsLast", type_name), - REQUIRED, proto, text, is_proto3); + // Test repeated data for singular fields. + // For scalar message fields, repeated values are merged, which is tested + // separately. + if (type != FieldDescriptor::TYPE_MESSAGE) { + std::string proto; + for (size_t i = 0; i < values.size(); i++) { + proto += absl::StrCat(tag(field->number(), wire_type), values[i].first); } + std::string expected_proto = + absl::StrCat(tag(field->number(), wire_type), values.back().second); + MessageType test_message; + test_message.MergeFromString(expected_proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + + RunValidProtobufTest(absl::StrCat("RepeatedScalarSelectsLast", type_name), + REQUIRED, proto, text); + } - // Test repeated fields. - if (FieldDescriptor::IsTypePackable(type)) { - const FieldDescriptor* packed_field = - GetFieldForType(type, true, is_proto3, Packed::kTrue); - const FieldDescriptor* unpacked_field = - GetFieldForType(type, true, is_proto3, Packed::kFalse); - - string default_proto_packed; - string default_proto_unpacked; - string default_proto_packed_expected; - string default_proto_unpacked_expected; - string packed_proto_packed; - string packed_proto_unpacked; - string packed_proto_expected; - string unpacked_proto_packed; - string unpacked_proto_unpacked; - string unpacked_proto_expected; - - for (size_t i = 0; i < values.size(); i++) { - default_proto_unpacked += - absl::StrCat(tag(rep_field->number(), wire_type), values[i].first); - default_proto_unpacked_expected += - absl::StrCat(tag(rep_field->number(), wire_type), values[i].second); - default_proto_packed += values[i].first; - default_proto_packed_expected += values[i].second; - packed_proto_unpacked += absl::StrCat( - tag(packed_field->number(), wire_type), values[i].first); - packed_proto_packed += values[i].first; - packed_proto_expected += values[i].second; - unpacked_proto_unpacked += absl::StrCat( - tag(unpacked_field->number(), wire_type), values[i].first); - unpacked_proto_packed += values[i].first; - unpacked_proto_expected += absl::StrCat( - tag(unpacked_field->number(), wire_type), values[i].second); - } - default_proto_packed = absl::StrCat( - tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(default_proto_packed)); - default_proto_packed_expected = absl::StrCat( - tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(default_proto_packed_expected)); - packed_proto_packed = - absl::StrCat(tag(packed_field->number(), - WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(packed_proto_packed)); - packed_proto_expected = - absl::StrCat(tag(packed_field->number(), - WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(packed_proto_expected)); - unpacked_proto_packed = - absl::StrCat(tag(unpacked_field->number(), - WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(unpacked_proto_packed)); - - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(default_proto_packed_expected); - string text; - TextFormat::PrintToString(*test_message, &text); - - // Ensures both packed and unpacked data can be parsed. - RunValidProtobufTest( - absl::StrCat("ValidDataRepeated", type_name, ".UnpackedInput"), - REQUIRED, default_proto_unpacked, text, is_proto3); - RunValidProtobufTest( - 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 - // packed by default. - string expected_proto = rep_field->is_packed() - ? default_proto_packed_expected - : default_proto_unpacked_expected; - RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, - ".UnpackedInput.DefaultOutput"), - RECOMMENDED, default_proto_unpacked, - expected_proto, is_proto3); - RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, - ".PackedInput.DefaultOutput"), - RECOMMENDED, default_proto_packed, - expected_proto, is_proto3); - RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, - ".UnpackedInput.PackedOutput"), - RECOMMENDED, packed_proto_unpacked, - packed_proto_expected, is_proto3); - RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, - ".PackedInput.PackedOutput"), - RECOMMENDED, packed_proto_packed, - packed_proto_expected, is_proto3); - RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, - ".UnpackedInput.UnpackedOutput"), - RECOMMENDED, unpacked_proto_unpacked, - unpacked_proto_expected, is_proto3); - RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, - ".PackedInput.UnpackedOutput"), - RECOMMENDED, unpacked_proto_packed, - unpacked_proto_expected, is_proto3); - } else { - string proto; - string expected_proto; - for (size_t i = 0; i < values.size(); i++) { - proto += - absl::StrCat(tag(rep_field->number(), wire_type), values[i].first); - expected_proto += - absl::StrCat(tag(rep_field->number(), wire_type), values[i].second); - } - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(expected_proto); - string text; - TextFormat::PrintToString(*test_message, &text); + // Test repeated fields. + if (FieldDescriptor::IsTypePackable(type)) { + const FieldDescriptor* packed_field = + GetFieldForType(type, true, Packed::kTrue); + const FieldDescriptor* unpacked_field = + GetFieldForType(type, true, Packed::kFalse); + + std::string default_proto_packed; + std::string default_proto_unpacked; + std::string default_proto_packed_expected; + std::string default_proto_unpacked_expected; + std::string packed_proto_packed; + std::string packed_proto_unpacked; + std::string packed_proto_expected; + std::string unpacked_proto_packed; + std::string unpacked_proto_unpacked; + std::string unpacked_proto_expected; - RunValidProtobufTest(absl::StrCat("ValidDataRepeated", type_name), - REQUIRED, proto, text, is_proto3); + for (size_t i = 0; i < values.size(); i++) { + default_proto_unpacked += + absl::StrCat(tag(rep_field->number(), wire_type), values[i].first); + default_proto_unpacked_expected += + absl::StrCat(tag(rep_field->number(), wire_type), values[i].second); + default_proto_packed += values[i].first; + default_proto_packed_expected += values[i].second; + packed_proto_unpacked += + absl::StrCat(tag(packed_field->number(), wire_type), values[i].first); + packed_proto_packed += values[i].first; + packed_proto_expected += values[i].second; + unpacked_proto_unpacked += absl::StrCat( + tag(unpacked_field->number(), wire_type), values[i].first); + unpacked_proto_packed += values[i].first; + unpacked_proto_expected += absl::StrCat( + tag(unpacked_field->number(), wire_type), values[i].second); } + default_proto_packed = absl::StrCat( + tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(default_proto_packed)); + default_proto_packed_expected = absl::StrCat( + tag(rep_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(default_proto_packed_expected)); + packed_proto_packed = absl::StrCat( + tag(packed_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(packed_proto_packed)); + packed_proto_expected = absl::StrCat( + tag(packed_field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(packed_proto_expected)); + unpacked_proto_packed = + absl::StrCat(tag(unpacked_field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(unpacked_proto_packed)); + + MessageType test_message; + test_message.MergeFromString(default_proto_packed_expected); + std::string text; + TextFormat::PrintToString(test_message, &text); + + // Ensures both packed and unpacked data can be parsed. + RunValidProtobufTest( + absl::StrCat("ValidDataRepeated", type_name, ".UnpackedInput"), + REQUIRED, default_proto_unpacked, text); + RunValidProtobufTest( + absl::StrCat("ValidDataRepeated", type_name, ".PackedInput"), REQUIRED, + default_proto_packed, text); + + // proto2 should encode as unpacked by default and proto3 should encode as + // packed by default. + std::string expected_proto = rep_field->is_packed() + ? default_proto_packed_expected + : default_proto_unpacked_expected; + RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, + ".UnpackedInput.DefaultOutput"), + RECOMMENDED, default_proto_unpacked, + expected_proto); + RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, + ".PackedInput.DefaultOutput"), + RECOMMENDED, default_proto_packed, + expected_proto); + RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, + ".UnpackedInput.PackedOutput"), + RECOMMENDED, packed_proto_unpacked, + packed_proto_expected); + RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, + ".PackedInput.PackedOutput"), + RECOMMENDED, packed_proto_packed, + packed_proto_expected); + RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, + ".UnpackedInput.UnpackedOutput"), + RECOMMENDED, unpacked_proto_unpacked, + unpacked_proto_expected); + RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name, + ".PackedInput.UnpackedOutput"), + RECOMMENDED, unpacked_proto_packed, + unpacked_proto_expected); + } else { + std::string proto; + std::string expected_proto; + for (size_t i = 0; i < values.size(); i++) { + proto += + absl::StrCat(tag(rep_field->number(), wire_type), values[i].first); + expected_proto += + absl::StrCat(tag(rep_field->number(), wire_type), values[i].second); + } + MessageType test_message; + test_message.MergeFromString(expected_proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + + RunValidProtobufTest(absl::StrCat("ValidDataRepeated", type_name), REQUIRED, + proto, text); } } -void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::TestValidDataForRepeatedScalarMessage() { std::vector values = { delim(absl::StrCat( tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), @@ -951,30 +912,28 @@ void BinaryAndJsonConformanceSuite::TestValidDataForRepeatedScalarMessage() { optional_int64: 1234, optional_uint32: 4321, repeated_int32: [1234, 4321], - } + } })"; - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - string proto; - const FieldDescriptor* field = - GetFieldForType(FieldDescriptor::TYPE_MESSAGE, false, is_proto3); - for (size_t i = 0; i < values.size(); i++) { - proto += absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - values[i]); - } - - RunValidProtobufTest("RepeatedScalarMessageMerge", REQUIRED, proto, - absl::StrCat(field->name(), ": ", expected), - is_proto3); + std::string proto; + const FieldDescriptor* field = + GetFieldForType(FieldDescriptor::TYPE_MESSAGE, false); + for (size_t i = 0; i < values.size(); i++) { + proto += absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + values[i]); } + + RunValidProtobufTest("RepeatedScalarMessageMerge", REQUIRED, proto, + absl::StrCat(field->name(), ": ", expected)); } -void BinaryAndJsonConformanceSuite::TestValidDataForMapType( +template +void BinaryAndJsonConformanceSuiteImpl::TestValidDataForMapType( FieldDescriptor::Type key_type, FieldDescriptor::Type value_type) { - const string key_type_name = + const std::string key_type_name = UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(key_type))); - const string value_type_name = + const std::string value_type_name = UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(value_type))); WireFormatLite::WireType key_wire_type = WireFormatLite::WireTypeForFieldType( static_cast(key_type)); @@ -982,436 +941,415 @@ void BinaryAndJsonConformanceSuite::TestValidDataForMapType( WireFormatLite::WireTypeForFieldType( static_cast(value_type)); - string key1_data = + std::string key1_data = absl::StrCat(tag(1, key_wire_type), GetDefaultValue(key_type)); - string value1_data = + std::string value1_data = absl::StrCat(tag(2, value_wire_type), GetDefaultValue(value_type)); - string key2_data = + std::string key2_data = absl::StrCat(tag(1, key_wire_type), GetNonDefaultValue(key_type)); - string value2_data = + std::string value2_data = absl::StrCat(tag(2, value_wire_type), GetNonDefaultValue(value_type)); - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - const FieldDescriptor* field = - GetFieldForMapType(key_type, value_type, is_proto3); - - { - // Tests map with default key and value. - string proto = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(key1_data, value1_data))); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, - value_type_name, ".Default"), - REQUIRED, proto, text, is_proto3); - } + const FieldDescriptor* field = GetFieldForMapType(key_type, value_type); - { - // Tests map with missing default key and value. - string proto = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim("")); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, - value_type_name, ".MissingDefault"), - REQUIRED, proto, text, is_proto3); - } + { + // Tests map with default key and value. + std::string proto = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(key1_data, value1_data))); + MessageType test_message; + test_message.MergeFromString(proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, + value_type_name, ".Default"), + REQUIRED, proto, text); + } - { - // Tests map with non-default key and value. - string proto = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(key2_data, value2_data))); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, - value_type_name, ".NonDefault"), - REQUIRED, proto, text, is_proto3); - } + { + // Tests map with missing default key and value. + std::string proto = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim("")); + MessageType test_message; + test_message.MergeFromString(proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, + value_type_name, ".MissingDefault"), + REQUIRED, proto, text); + } - { - // Tests map with unordered key and value. - string proto = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(value2_data, key2_data))); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, - value_type_name, ".Unordered"), - REQUIRED, proto, text, is_proto3); - } + { + // Tests map with non-default key and value. + std::string proto = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(key2_data, value2_data))); + MessageType test_message; + test_message.MergeFromString(proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, + value_type_name, ".NonDefault"), + REQUIRED, proto, text); + } - { - // Tests map with duplicate key. - string proto1 = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(key2_data, value1_data))); - string proto2 = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(key2_data, value2_data))); - string proto = absl::StrCat(proto1, proto2); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto2); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, - value_type_name, ".DuplicateKey"), - REQUIRED, proto, text, is_proto3); - } + { + // Tests map with unordered key and value. + std::string proto = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(value2_data, key2_data))); + MessageType test_message; + test_message.MergeFromString(proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, + value_type_name, ".Unordered"), + REQUIRED, proto, text); + } - { - // Tests map with duplicate key in map entry. - string proto = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(key1_data, key2_data, value2_data))); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest( - absl::StrCat("ValidDataMap", key_type_name, value_type_name, - ".DuplicateKeyInMapEntry"), - REQUIRED, proto, text, is_proto3); - } + { + // Tests map with duplicate key. + std::string proto1 = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(key2_data, value1_data))); + std::string proto2 = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(key2_data, value2_data))); + std::string proto = absl::StrCat(proto1, proto2); + MessageType test_message; + test_message.MergeFromString(proto2); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name, + value_type_name, ".DuplicateKey"), + REQUIRED, proto, text); + } - { - // Tests map with duplicate value in map entry. - string proto = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(key2_data, value1_data, value2_data))); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest( - absl::StrCat("ValidDataMap", key_type_name, value_type_name, - ".DuplicateValueInMapEntry"), - REQUIRED, proto, text, is_proto3); - } + { + // Tests map with duplicate key in map entry. + std::string proto = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(key1_data, key2_data, value2_data))); + MessageType test_message; + test_message.MergeFromString(proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest( + absl::StrCat("ValidDataMap", key_type_name, value_type_name, + ".DuplicateKeyInMapEntry"), + REQUIRED, proto, text); + } + + { + // Tests map with duplicate value in map entry. + std::string proto = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(key2_data, value1_data, value2_data))); + MessageType test_message; + test_message.MergeFromString(proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest( + absl::StrCat("ValidDataMap", key_type_name, value_type_name, + ".DuplicateValueInMapEntry"), + REQUIRED, proto, text); } } -void BinaryAndJsonConformanceSuite::TestOverwriteMessageValueMap() { - string key_data = absl::StrCat( +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::TestOverwriteMessageValueMap() { + std::string key_data = absl::StrCat( tag(1, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim("")); - string field1_data = + std::string field1_data = absl::StrCat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1)); - string field2_data = + std::string field2_data = absl::StrCat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); - string field31_data = + std::string field31_data = absl::StrCat(tag(31, WireFormatLite::WIRETYPE_VARINT), varint(1)); - string submsg1_data = delim(absl::StrCat(field1_data, field31_data)); - string submsg2_data = delim(absl::StrCat(field2_data, field31_data)); - string value1_data = absl::StrCat( + std::string submsg1_data = delim(absl::StrCat(field1_data, field31_data)); + std::string submsg2_data = delim(absl::StrCat(field2_data, field31_data)); + std::string value1_data = absl::StrCat( tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(absl::StrCat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), submsg1_data))); - string value2_data = absl::StrCat( + std::string value2_data = absl::StrCat( tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(absl::StrCat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), submsg2_data))); - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - const FieldDescriptor* field = GetFieldForMapType( - FieldDescriptor::TYPE_STRING, FieldDescriptor::TYPE_MESSAGE, is_proto3); - - string proto1 = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(key_data, value1_data))); - string proto2 = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(absl::StrCat(key_data, value2_data))); - string proto = absl::StrCat(proto1, proto2); - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto2); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest("ValidDataMap.STRING.MESSAGE.MergeValue", REQUIRED, - proto, text, is_proto3); - } + const FieldDescriptor* field = GetFieldForMapType( + FieldDescriptor::TYPE_STRING, FieldDescriptor::TYPE_MESSAGE); + + std::string proto1 = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(key_data, value1_data))); + std::string proto2 = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(absl::StrCat(key_data, value2_data))); + std::string proto = absl::StrCat(proto1, proto2); + MessageType test_message; + test_message.MergeFromString(proto2); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest("ValidDataMap.STRING.MESSAGE.MergeValue", REQUIRED, + proto, text); } -void BinaryAndJsonConformanceSuite::TestValidDataForOneofType( +template +void BinaryAndJsonConformanceSuiteImpl::TestValidDataForOneofType( FieldDescriptor::Type type) { - const string type_name = + const std::string type_name = UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type))); WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( static_cast(type)); - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - const FieldDescriptor* field = GetFieldForOneofType(type, is_proto3); - const string default_value = - absl::StrCat(tag(field->number(), wire_type), GetDefaultValue(type)); - const string non_default_value = - absl::StrCat(tag(field->number(), wire_type), GetNonDefaultValue(type)); - - { - // Tests oneof with default value. - const string proto = default_value; - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto); - string text; - TextFormat::PrintToString(*test_message, &text); - - RunValidProtobufTest( - absl::StrCat("ValidDataOneof", type_name, ".DefaultValue"), REQUIRED, - proto, text, is_proto3); - RunValidBinaryProtobufTest( - absl::StrCat("ValidDataOneofBinary", type_name, ".DefaultValue"), - RECOMMENDED, proto, proto, is_proto3); - } + const FieldDescriptor* field = GetFieldForOneofType(type); + const std::string default_value = + absl::StrCat(tag(field->number(), wire_type), GetDefaultValue(type)); + const std::string non_default_value = + absl::StrCat(tag(field->number(), wire_type), GetNonDefaultValue(type)); - { - // Tests oneof with non-default value. - const string proto = non_default_value; - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(proto); - string text; - TextFormat::PrintToString(*test_message, &text); - - RunValidProtobufTest( - absl::StrCat("ValidDataOneof", type_name, ".NonDefaultValue"), - REQUIRED, proto, text, is_proto3); - RunValidBinaryProtobufTest( - absl::StrCat("ValidDataOneofBinary", type_name, ".NonDefaultValue"), - RECOMMENDED, proto, proto, is_proto3); - } + { + // Tests oneof with default value. + const std::string proto = default_value; + MessageType test_message; + test_message.MergeFromString(proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + + RunValidProtobufTest( + absl::StrCat("ValidDataOneof", type_name, ".DefaultValue"), REQUIRED, + proto, text); + RunValidBinaryProtobufTest( + absl::StrCat("ValidDataOneofBinary", type_name, ".DefaultValue"), + RECOMMENDED, proto, proto); + } - { - // Tests oneof with multiple values of the same field. - const string proto = absl::StrCat(default_value, non_default_value); - const string expected_proto = non_default_value; - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(expected_proto); - string text; - TextFormat::PrintToString(*test_message, &text); - - RunValidProtobufTest(absl::StrCat("ValidDataOneof", type_name, - ".MultipleValuesForSameField"), - REQUIRED, proto, text, is_proto3); - RunValidBinaryProtobufTest(absl::StrCat("ValidDataOneofBinary", type_name, - ".MultipleValuesForSameField"), - RECOMMENDED, proto, expected_proto, is_proto3); - } + { + // Tests oneof with non-default value. + const std::string proto = non_default_value; + MessageType test_message; + test_message.MergeFromString(proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + + RunValidProtobufTest( + absl::StrCat("ValidDataOneof", type_name, ".NonDefaultValue"), REQUIRED, + proto, text); + RunValidBinaryProtobufTest( + absl::StrCat("ValidDataOneofBinary", type_name, ".NonDefaultValue"), + RECOMMENDED, proto, proto); + } - { - // Tests oneof with multiple values of the different fields. - const FieldDescriptor* other_field = - GetFieldForOneofType(type, is_proto3, true); - FieldDescriptor::Type other_type = other_field->type(); - WireFormatLite::WireType other_wire_type = - WireFormatLite::WireTypeForFieldType( - static_cast(other_type)); - const string other_value = - absl::StrCat(tag(other_field->number(), other_wire_type), - GetDefaultValue(other_type)); - - const string proto = absl::StrCat(other_value, non_default_value); - const string expected_proto = non_default_value; - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(expected_proto); - string text; - TextFormat::PrintToString(*test_message, &text); - - RunValidProtobufTest(absl::StrCat("ValidDataOneof", type_name, - ".MultipleValuesForDifferentField"), - REQUIRED, proto, text, is_proto3); - RunValidBinaryProtobufTest( - absl::StrCat("ValidDataOneofBinary", type_name, - ".MultipleValuesForDifferentField"), - RECOMMENDED, proto, expected_proto, is_proto3); - } + { + // Tests oneof with multiple values of the same field. + const std::string proto = absl::StrCat(default_value, non_default_value); + const std::string expected_proto = non_default_value; + MessageType test_message; + test_message.MergeFromString(expected_proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + + RunValidProtobufTest(absl::StrCat("ValidDataOneof", type_name, + ".MultipleValuesForSameField"), + REQUIRED, proto, text); + RunValidBinaryProtobufTest(absl::StrCat("ValidDataOneofBinary", type_name, + ".MultipleValuesForSameField"), + RECOMMENDED, proto, expected_proto); + } + + { + // Tests oneof with multiple values of the different fields. + const FieldDescriptor* other_field = GetFieldForOneofType(type, true); + FieldDescriptor::Type other_type = other_field->type(); + WireFormatLite::WireType other_wire_type = + WireFormatLite::WireTypeForFieldType( + static_cast(other_type)); + const std::string other_value = + absl::StrCat(tag(other_field->number(), other_wire_type), + GetDefaultValue(other_type)); + + const std::string proto = absl::StrCat(other_value, non_default_value); + const std::string expected_proto = non_default_value; + MessageType test_message; + test_message.MergeFromString(expected_proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + + RunValidProtobufTest(absl::StrCat("ValidDataOneof", type_name, + ".MultipleValuesForDifferentField"), + REQUIRED, proto, text); + RunValidBinaryProtobufTest(absl::StrCat("ValidDataOneofBinary", type_name, + ".MultipleValuesForDifferentField"), + RECOMMENDED, proto, expected_proto); } } -void BinaryAndJsonConformanceSuite::TestMergeOneofMessage() { - string field1_data = +template +void BinaryAndJsonConformanceSuiteImpl::TestMergeOneofMessage() { + std::string field1_data = absl::StrCat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1)); - string field2a_data = + std::string field2a_data = absl::StrCat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); - string field2b_data = + std::string field2b_data = absl::StrCat(tag(2, WireFormatLite::WIRETYPE_VARINT), varint(1)); - string field89_data = + std::string field89_data = absl::StrCat(tag(89, WireFormatLite::WIRETYPE_VARINT), varint(1)); - string submsg1_data = absl::StrCat( + std::string submsg1_data = absl::StrCat( tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(absl::StrCat(field1_data, field2a_data, field89_data))); - string submsg2_data = + std::string submsg2_data = absl::StrCat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(absl::StrCat(field2b_data, field89_data))); - string merged_data = + std::string merged_data = absl::StrCat(tag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(absl::StrCat(field1_data, field2b_data, field89_data, field89_data))); - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - const FieldDescriptor* field = - GetFieldForOneofType(FieldDescriptor::TYPE_MESSAGE, is_proto3); - - string proto1 = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(submsg1_data)); - string proto2 = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(submsg2_data)); - string proto = absl::StrCat(proto1, proto2); - string expected_proto = absl::StrCat( - tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), - delim(merged_data)); - - std::unique_ptr test_message = NewTestMessage(is_proto3); - test_message->MergeFromString(expected_proto); - string text; - TextFormat::PrintToString(*test_message, &text); - RunValidProtobufTest("ValidDataOneof.MESSAGE.Merge", REQUIRED, proto, text, - is_proto3); - RunValidBinaryProtobufTest("ValidDataOneofBinary.MESSAGE.Merge", - RECOMMENDED, proto, expected_proto, is_proto3); - } + const FieldDescriptor* field = + GetFieldForOneofType(FieldDescriptor::TYPE_MESSAGE); + + std::string proto1 = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(submsg1_data)); + std::string proto2 = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(submsg2_data)); + std::string proto = absl::StrCat(proto1, proto2); + std::string expected_proto = absl::StrCat( + tag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(merged_data)); + + MessageType test_message; + test_message.MergeFromString(expected_proto); + std::string text; + TextFormat::PrintToString(test_message, &text); + RunValidProtobufTest("ValidDataOneof.MESSAGE.Merge", REQUIRED, proto, text); + RunValidBinaryProtobufTest("ValidDataOneofBinary.MESSAGE.Merge", RECOMMENDED, + proto, expected_proto); } -void BinaryAndJsonConformanceSuite::TestIllegalTags() { +template +void BinaryAndJsonConformanceSuiteImpl::TestIllegalTags() { // field num 0 is illegal - string nullfield[] = {"\1DEADBEEF", "\2\1\1", "\3\4", "\5DEAD"}; + std::string nullfield[] = {"\1DEADBEEF", "\2\1\1", "\3\4", "\5DEAD"}; for (int i = 0; i < 4; i++) { - string name = "IllegalZeroFieldNum_Case_0"; + std::string name = "IllegalZeroFieldNum_Case_0"; name.back() += i; ExpectParseFailureForProto(nullfield[i], name, REQUIRED); } } -template -void BinaryAndJsonConformanceSuite::TestOneofMessage(MessageType& message, - bool is_proto3) { + +template +void BinaryAndJsonConformanceSuiteImpl::TestOneofMessage() { + MessageType message; message.set_oneof_uint32(0); RunValidProtobufTestWithMessage("OneofZeroUint32", RECOMMENDED, &message, - "oneof_uint32: 0", is_proto3); + "oneof_uint32: 0"); message.mutable_oneof_nested_message()->set_a(0); - RunValidProtobufTestWithMessage( - "OneofZeroMessage", RECOMMENDED, &message, - is_proto3 ? "oneof_nested_message: {}" : "oneof_nested_message: {a: 0}", - is_proto3); + RunValidProtobufTestWithMessage("OneofZeroMessage", RECOMMENDED, &message, + run_proto3_tests_ + ? "oneof_nested_message: {}" + : "oneof_nested_message: {a: 0}"); message.mutable_oneof_nested_message()->set_a(1); RunValidProtobufTestWithMessage("OneofZeroMessageSetTwice", RECOMMENDED, - &message, "oneof_nested_message: {a: 1}", - is_proto3); + &message, "oneof_nested_message: {a: 1}"); message.set_oneof_string(""); RunValidProtobufTestWithMessage("OneofZeroString", RECOMMENDED, &message, - "oneof_string: \"\"", is_proto3); + "oneof_string: \"\""); message.set_oneof_bytes(""); RunValidProtobufTestWithMessage("OneofZeroBytes", RECOMMENDED, &message, - "oneof_bytes: \"\"", is_proto3); + "oneof_bytes: \"\""); message.set_oneof_bool(false); RunValidProtobufTestWithMessage("OneofZeroBool", RECOMMENDED, &message, - "oneof_bool: false", is_proto3); + "oneof_bool: false"); message.set_oneof_uint64(0); RunValidProtobufTestWithMessage("OneofZeroUint64", RECOMMENDED, &message, - "oneof_uint64: 0", is_proto3); + "oneof_uint64: 0"); message.set_oneof_float(0.0f); RunValidProtobufTestWithMessage("OneofZeroFloat", RECOMMENDED, &message, - "oneof_float: 0", is_proto3); + "oneof_float: 0"); message.set_oneof_double(0.0); RunValidProtobufTestWithMessage("OneofZeroDouble", RECOMMENDED, &message, - "oneof_double: 0", is_proto3); + "oneof_double: 0"); message.set_oneof_enum(MessageType::FOO); RunValidProtobufTestWithMessage("OneofZeroEnum", RECOMMENDED, &message, - "oneof_enum: FOO", is_proto3); + "oneof_enum: FOO"); } -template -void BinaryAndJsonConformanceSuite::TestUnknownMessage(MessageType& message, - bool is_proto3) { +template +void BinaryAndJsonConformanceSuiteImpl::TestUnknownMessage() { + MessageType message; message.ParseFromString("\xA8\x1F\x01"); RunValidBinaryProtobufTest("UnknownVarint", REQUIRED, - message.SerializeAsString(), is_proto3); + message.SerializeAsString()); } -void BinaryAndJsonConformanceSuite:: - TestBinaryPerformanceForAlternatingUnknownFields() { - string unknown_field_1 = absl::StrCat( +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::TestBinaryPerformanceForAlternatingUnknownFields() { + std::string unknown_field_1 = absl::StrCat( tag(UNKNOWN_FIELD, WireFormatLite::WIRETYPE_VARINT), varint(1234)); - string unknown_field_2 = absl::StrCat( + std::string unknown_field_2 = absl::StrCat( tag(UNKNOWN_FIELD + 1, WireFormatLite::WIRETYPE_VARINT), varint(5678)); - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - string proto; - for (size_t i = 0; i < kPerformanceRepeatCount; i++) { - proto.append(unknown_field_1); - proto.append(unknown_field_2); - } - - RunValidBinaryProtobufTest( - "TestBinaryPerformanceForAlternatingUnknownFields", RECOMMENDED, proto, - is_proto3); + std::string proto; + for (size_t i = 0; i < kPerformanceRepeatCount; i++) { + proto.append(unknown_field_1); + proto.append(unknown_field_2); } + + RunValidBinaryProtobufTest("TestBinaryPerformanceForAlternatingUnknownFields", + RECOMMENDED, proto); } -void BinaryAndJsonConformanceSuite:: +template +void BinaryAndJsonConformanceSuiteImpl:: TestBinaryPerformanceMergeMessageWithRepeatedFieldForType( FieldDescriptor::Type type) { - const string type_name = + const std::string type_name = UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type))); - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - int field_number = - GetFieldForType(type, true, is_proto3, Packed::kFalse)->number(); - string rep_field_proto = absl::StrCat( - tag(field_number, WireFormatLite::WireTypeForFieldType( - static_cast(type))), - GetNonDefaultValue(type)); - - RunBinaryPerformanceMergeMessageWithField( - absl::StrCat( - "TestBinaryPerformanceMergeMessageWithRepeatedFieldForType", - type_name), - rep_field_proto, is_proto3); - } + int field_number = GetFieldForType(type, true, Packed::kFalse)->number(); + std::string rep_field_proto = absl::StrCat( + tag(field_number, WireFormatLite::WireTypeForFieldType( + static_cast(type))), + GetNonDefaultValue(type)); + + RunBinaryPerformanceMergeMessageWithField( + absl::StrCat("TestBinaryPerformanceMergeMessageWithRepeatedFieldForType", + type_name), + rep_field_proto); } -void BinaryAndJsonConformanceSuite:: +template +void BinaryAndJsonConformanceSuiteImpl:: TestBinaryPerformanceMergeMessageWithUnknownFieldForType( FieldDescriptor::Type type) { - const string type_name = + const std::string type_name = UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type))); - string unknown_field_proto = absl::StrCat( + std::string unknown_field_proto = absl::StrCat( tag(UNKNOWN_FIELD, WireFormatLite::WireTypeForFieldType( static_cast(type))), GetNonDefaultValue(type)); - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - RunBinaryPerformanceMergeMessageWithField( - absl::StrCat("TestBinaryPerformanceMergeMessageWithUnknownFieldForType", - type_name), - unknown_field_proto, is_proto3); - } + RunBinaryPerformanceMergeMessageWithField( + absl::StrCat("TestBinaryPerformanceMergeMessageWithUnknownFieldForType", + type_name), + unknown_field_proto); } -void BinaryAndJsonConformanceSuite::RunSuiteImpl() { - // Hack to get the list of test failures based on whether - // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER is enabled or not. - conformance::FailureSet failure_set; - ConformanceRequest req; - ConformanceResponse res; - req.set_message_type(failure_set.GetTypeName()); - req.set_protobuf_payload(""); - req.set_requested_output_format(conformance::WireFormat::PROTOBUF); - RunTest("FindFailures", req, &res); - ABSL_CHECK(failure_set.MergeFromString(res.protobuf_payload())); - for (const string& failure : failure_set.failure()) { - AddExpectedFailedTest(failure); - } - - type_resolver_.reset(NewTypeResolverForDescriptorPool( - kTypeUrlPrefix, DescriptorPool::generated_pool())); - type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor()); +template +BinaryAndJsonConformanceSuiteImpl:: + BinaryAndJsonConformanceSuiteImpl(BinaryAndJsonConformanceSuite* suite, + bool run_proto3_tests) + : suite_(*ABSL_DIE_IF_NULL(suite)), run_proto3_tests_(run_proto3_tests) { + suite_.SetTypeUrl(GetTypeUrl(MessageType::GetDescriptor())); + RunAllTests(); +} - if (!performance_) { +template +void BinaryAndJsonConformanceSuiteImpl::RunAllTests() { + if (!suite_.performance_) { for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) { if (i == FieldDescriptor::TYPE_GROUP) continue; TestPrematureEOFForType(static_cast(i)); @@ -1630,27 +1568,25 @@ void BinaryAndJsonConformanceSuite::RunSuiteImpl() { // TestValidDataForType(FieldDescriptor::TYPE_GROUP // Unknown fields. - { - TestAllTypesProto3 messageProto3; - TestAllTypesProto2 messageProto2; - // TODO: update this behavior when unknown field's behavior - // changed in open source. Also delete - // Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput - // from failure list of python_cpp python java - TestUnknownMessage(messageProto3, true); - TestUnknownMessage(messageProto2, false); - } + // TODO: update this behavior when unknown field's behavior + // changed in open source. Also delete + // Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput + // from failure list of python_cpp python java + TestUnknownMessage(); + TestOneofMessage(); RunJsonTests(); } // Flag control performance tests to keep them internal and opt-in only - if (performance_) { + if (suite_.performance_) { RunBinaryPerformanceTests(); RunJsonPerformanceTests(); } } -void BinaryAndJsonConformanceSuite::RunBinaryPerformanceTests() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunBinaryPerformanceTests() { TestBinaryPerformanceForAlternatingUnknownFields(); TestBinaryPerformanceMergeMessageWithRepeatedFieldForType( @@ -1684,7 +1620,8 @@ void BinaryAndJsonConformanceSuite::RunBinaryPerformanceTests() { FieldDescriptor::TYPE_BYTES); } -void BinaryAndJsonConformanceSuite::RunJsonPerformanceTests() { +template +void BinaryAndJsonConformanceSuiteImpl::RunJsonPerformanceTests() { TestJsonPerformanceMergeMessageWithRepeatedFieldForType( FieldDescriptor::TYPE_BOOL, "true"); TestJsonPerformanceMergeMessageWithRepeatedFieldForType( @@ -1702,41 +1639,61 @@ void BinaryAndJsonConformanceSuite::RunJsonPerformanceTests() { } // This is currently considered valid input by some languages but not others -void BinaryAndJsonConformanceSuite:: +template +void BinaryAndJsonConformanceSuiteImpl:: TestJsonPerformanceMergeMessageWithRepeatedFieldForType( - FieldDescriptor::Type type, string field_value) { - const string type_name = + FieldDescriptor::Type type, std::string field_value) { + const std::string type_name = UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type))); - for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) { - const FieldDescriptor* field = - GetFieldForType(type, true, is_proto3, Packed::kFalse); - string field_name = field->name(); - - string message_field = - absl::StrCat("\"", field_name, "\": [", field_value, "]"); - string recursive_message = - absl::StrCat("\"recursive_message\": { ", message_field, "}"); - string input = absl::StrCat("{", recursive_message); - for (size_t i = 1; i < kPerformanceRepeatCount; i++) { - absl::StrAppend(&input, ",", recursive_message); - } - absl::StrAppend(&input, "}"); + const FieldDescriptor* field = GetFieldForType(type, true, Packed::kFalse); + std::string field_name = field->name(); + + std::string message_field = + absl::StrCat("\"", field_name, "\": [", field_value, "]"); + std::string recursive_message = + absl::StrCat("\"recursive_message\": { ", message_field, "}"); + std::string input = absl::StrCat("{", recursive_message); + for (size_t i = 1; i < kPerformanceRepeatCount; i++) { + absl::StrAppend(&input, ",", recursive_message); + } + absl::StrAppend(&input, "}"); - string textproto_message_field = - absl::StrCat(field_name, ": ", field_value); - string expected_textproto = "recursive_message { "; - for (size_t i = 0; i < kPerformanceRepeatCount; i++) { - absl::StrAppend(&expected_textproto, textproto_message_field, " "); - } - absl::StrAppend(&expected_textproto, "}"); - RunValidJsonTest( - absl::StrCat("TestJsonPerformanceMergeMessageWithRepeatedFieldForType", - type_name), - RECOMMENDED, input, expected_textproto, is_proto3); + std::string textproto_message_field = + absl::StrCat(field_name, ": ", field_value); + std::string expected_textproto = "recursive_message { "; + for (size_t i = 0; i < kPerformanceRepeatCount; i++) { + absl::StrAppend(&expected_textproto, textproto_message_field, " "); } + absl::StrAppend(&expected_textproto, "}"); + RunValidJsonTest( + absl::StrCat("TestJsonPerformanceMergeMessageWithRepeatedFieldForType", + type_name), + RECOMMENDED, input, expected_textproto); } -void BinaryAndJsonConformanceSuite::RunJsonTests() { +template +void BinaryAndJsonConformanceSuiteImpl::RunJsonTests() { + if (!run_proto3_tests_) { + RunValidJsonTestWithValidator( + "StoresDefaultPrimitive", REQUIRED, + R"({ + "FieldName13": 0 + })", + [](const Json::Value& value) { return value.isMember("FieldName13"); }); + std::vector extensions; + MessageType::GetDescriptor()->file()->pool()->FindAllExtensions( + MessageType::GetDescriptor(), &extensions); + RunValidJsonTestWithValidator("FieldNameExtension", RECOMMENDED, + absl::Substitute(R"({ + "[$0]": 1 + })", + extensions[0]->full_name()), + [&](const Json::Value& value) { + return value.isMember(absl::StrCat( + "[", extensions[0]->full_name(), "]")); + }); + return; + } RunValidJsonTest("HelloWorld", REQUIRED, "{\"optionalString\":\"Hello, World!\"}", "optional_string: 'Hello, World!'"); @@ -1789,16 +1746,18 @@ void BinaryAndJsonConformanceSuite::RunJsonTests() { ExpectParseFailureForJson("RejectTopLevelNull", REQUIRED, "null"); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForUnknownEnumStringValues() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunJsonTestsForUnknownEnumStringValues() { // Tests the handling of unknown enum values when encoded as string labels. // The expected behavior depends on whether unknown fields are ignored: // * when ignored, the parser should ignore the unknown enum string value. // * when not ignored, the parser should fail. struct TestCase { // Used in the test name. - string enum_location; + std::string enum_location; // JSON input which will contain the unknown field. - string input_json; + std::string input_json; }; const std::vector test_cases = { {"InOptionalField", R"json({ @@ -1824,7 +1783,9 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForUnknownEnumStringValues() { } } -void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldNameConvention() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunJsonTestsForFieldNameConvention() { RunValidJsonTest("FieldNameInSnakeCase", REQUIRED, R"({ "fieldname1": 1, @@ -1998,29 +1959,28 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldNameConvention() { "optional_nested_message": {} })"); // Serializers should use lowerCamelCase by default. - RunValidJsonTestWithValidator( - "FieldNameInLowerCamelCase", REQUIRED, - R"({ + RunValidJsonTestWithValidator("FieldNameInLowerCamelCase", REQUIRED, + R"({ "fieldname1": 1, "fieldName2": 2, "FieldName3": 3, "fieldName4": 4 })", - [](const Json::Value& value) { - return value.isMember("fieldname1") && value.isMember("fieldName2") && - value.isMember("FieldName3") && value.isMember("fieldName4"); - }, - true); - RunValidJsonTestWithValidator( - "FieldNameWithNumbers", REQUIRED, - R"({ + [](const Json::Value& value) { + return value.isMember("fieldname1") && + value.isMember("fieldName2") && + value.isMember("FieldName3") && + value.isMember("fieldName4"); + }); + RunValidJsonTestWithValidator("FieldNameWithNumbers", REQUIRED, + R"({ "field0name5": 5, "field0Name6": 6 })", - [](const Json::Value& value) { - return value.isMember("field0name5") && value.isMember("field0Name6"); - }, - true); + [](const Json::Value& value) { + return value.isMember("field0name5") && + value.isMember("field0Name6"); + }); RunValidJsonTestWithValidator( "FieldNameWithMixedCases", REQUIRED, R"({ @@ -2035,8 +1995,7 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldNameConvention() { return value.isMember("fieldName7") && value.isMember("FieldName8") && value.isMember("fieldName9") && value.isMember("FieldName10") && value.isMember("FIELDNAME11") && value.isMember("FIELDName12"); - }, - true); + }); RunValidJsonTestWithValidator( "FieldNameWithDoubleUnderscores", RECOMMENDED, R"({ @@ -2051,35 +2010,18 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldNameConvention() { return value.isMember("FieldName13") && value.isMember("FieldName14") && value.isMember("fieldName15") && value.isMember("fieldName16") && value.isMember("fieldName17") && value.isMember("FieldName18"); - }, - true); - RunValidJsonTestWithValidator( - "StoresDefaultPrimitive", REQUIRED, - R"({ - "FieldName13": 0 - })", - [](const Json::Value& value) { return value.isMember("FieldName13"); }, - false); + }); RunValidJsonTestWithValidator( "SkipsDefaultPrimitive", REQUIRED, R"({ "FieldName13": 0 })", - [](const Json::Value& value) { return !value.isMember("FieldName13"); }, - true); - RunValidJsonTestWithValidator( - "FieldNameExtension", RECOMMENDED, - R"({ - "[protobuf_test_messages.proto2.extension_int32]": 1 - })", - [](const Json::Value& value) { - return value.isMember( - "[protobuf_test_messages.proto2.extension_int32]"); - }, - false); + [](const Json::Value& value) { return !value.isMember("FieldName13"); }); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunJsonTestsForNonRepeatedTypes() { // Integer fields. RunValidJsonTest("Int32FieldMaxValue", REQUIRED, R"({"optionalInt32": 2147483647})", @@ -2193,15 +2135,13 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { [](const Json::Value& value) { return value["optionalInt64"].type() == Json::stringValue && value["optionalInt64"].asString() == "1"; - }, - true); + }); RunValidJsonTestWithValidator( "Uint64FieldBeString", RECOMMENDED, R"({"optionalUint64": 1})", [](const Json::Value& value) { return value["optionalUint64"].type() == Json::stringValue && value["optionalUint64"].asString() == "1"; - }, - true); + }); // Bool fields. RunValidJsonTest("BoolFieldTrue", REQUIRED, R"({"optionalBool":true})", @@ -2252,7 +2192,7 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { R"({"optionalFloat": "-Infinity"})", "optional_float: -inf"); // Non-canonical Nan will be correctly normalized. { - TestAllTypesProto3 message; + MessageType message; // IEEE floating-point standard 32-bit quiet NaN: // 0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx message.set_optional_float(WireFormatLite::DecodeFloat(0x7FA12345)); @@ -2304,7 +2244,7 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { "optional_double: -inf"); // Non-canonical Nan will be correctly normalized. { - TestAllTypesProto3 message; + MessageType message; message.set_optional_double( WireFormatLite::DecodeDouble(int64_t{0x7FFA123456789ABC})); RunValidJsonTestWithProtobufInput("DoubleFieldNormalizeQuietNan", REQUIRED, @@ -2360,8 +2300,7 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { [](const Json::Value& value) { return value["optionalNestedEnum"].type() == Json::intValue && value["optionalNestedEnum"].asInt() == 123; - }, - true); + }); // String fields. RunValidJsonTest("StringField", REQUIRED, @@ -2425,11 +2364,6 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { RunValidJsonTest("OneofFieldNullSecond", REQUIRED, R"({"oneofString": "test", "oneofUint32": null})", "oneof_string: \"test\""); - // Ensure zero values for oneof make it out/backs. - TestAllTypesProto3 messageProto3; - TestAllTypesProto2 messageProto2; - TestOneofMessage(messageProto3, true); - TestOneofMessage(messageProto2, false); RunValidJsonTest("OneofZeroUint32", RECOMMENDED, R"({"oneofUint32": 0})", "oneof_uint32: 0"); RunValidJsonTest("OneofZeroMessage", RECOMMENDED, @@ -2485,17 +2419,17 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { "mapStringNestedMessage": { "hello": {"a": 1234}, "world": {"a": 5678} - } + } })", R"( map_string_nested_message: { key: "hello" value: {a: 1234} - } + } map_string_nested_message: { key: "world" value: {a: 5678} - } + } )"); // Since Map keys are represented as JSON strings, escaping should be allowed. RunValidJsonTest("Int32MapEscapedKey", REQUIRED, @@ -2518,7 +2452,9 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNonRepeatedTypes() { R"({'optionalString': 'Hello world!'})"); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForRepeatedTypes() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunJsonTestsForRepeatedTypes() { // Repeated fields. RunValidJsonTest("PrimitiveRepeatedField", REQUIRED, R"({"repeatedInt32": [1, 2, 3, 4]})", @@ -2578,7 +2514,9 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForRepeatedTypes() { "{\"repeatedInt32\": [\n 1,\n 2,\n 3,\n 4,\n]}"); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForNullTypes() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunJsonTestsForNullTypes() { // "null" is accepted for all fields types. RunValidJsonTest("AllFieldAcceptNull", REQUIRED, R"({ @@ -2636,7 +2574,9 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForNullTypes() { R"({"mapInt32Int32": {"0": null}})"); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForWrapperTypes() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunJsonTestsForWrapperTypes() { RunValidJsonTest("OptionalBoolWrapper", REQUIRED, R"({"optionalBoolWrapper": false})", "optional_bool_wrapper: {value: false}"); @@ -2789,32 +2729,24 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForWrapperTypes() { RunValidJsonTestWithValidator( "DurationHasZeroFractionalDigit", RECOMMENDED, - R"({"optionalDuration": "1.000000000s"})", - [](const Json::Value& value) { + R"({"optionalDuration": "1.000000000s"})", [](const Json::Value& value) { return value["optionalDuration"].asString() == "1s"; - }, - true); + }); RunValidJsonTestWithValidator( "DurationHas3FractionalDigits", RECOMMENDED, - R"({"optionalDuration": "1.010000000s"})", - [](const Json::Value& value) { + R"({"optionalDuration": "1.010000000s"})", [](const Json::Value& value) { return value["optionalDuration"].asString() == "1.010s"; - }, - true); + }); RunValidJsonTestWithValidator( "DurationHas6FractionalDigits", RECOMMENDED, - R"({"optionalDuration": "1.000010000s"})", - [](const Json::Value& value) { + R"({"optionalDuration": "1.000010000s"})", [](const Json::Value& value) { return value["optionalDuration"].asString() == "1.000010s"; - }, - true); + }); RunValidJsonTestWithValidator( "DurationHas9FractionalDigits", RECOMMENDED, - R"({"optionalDuration": "1.000000010s"})", - [](const Json::Value& value) { + R"({"optionalDuration": "1.000000010s"})", [](const Json::Value& value) { return value["optionalDuration"].asString() == "1.000000010s"; - }, - true); + }); // Timestamp RunValidJsonTest("TimestampMinValue", REQUIRED, @@ -2830,7 +2762,7 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForWrapperTypes() { "repeatedTimestamp": [ "0001-01-01T00:00:00Z", "9999-12-31T23:59:59.999999999Z" - ] + ] })", "repeated_timestamp: {seconds: -62135596800}" "repeated_timestamp: {seconds: 253402300799 nanos: 999999999}"); @@ -2868,42 +2800,39 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForWrapperTypes() { R"({"optionalTimestamp": "1969-12-31T16:00:00-08:00"})", [](const Json::Value& value) { return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00Z"; - }, - true); + }); RunValidJsonTestWithValidator( "TimestampHasZeroFractionalDigit", RECOMMENDED, R"({"optionalTimestamp": "1970-01-01T00:00:00.000000000Z"})", [](const Json::Value& value) { return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00Z"; - }, - true); + }); RunValidJsonTestWithValidator( "TimestampHas3FractionalDigits", RECOMMENDED, R"({"optionalTimestamp": "1970-01-01T00:00:00.010000000Z"})", [](const Json::Value& value) { return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00.010Z"; - }, - true); + }); RunValidJsonTestWithValidator( "TimestampHas6FractionalDigits", RECOMMENDED, R"({"optionalTimestamp": "1970-01-01T00:00:00.000010000Z"})", [](const Json::Value& value) { return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00.000010Z"; - }, - true); + }); RunValidJsonTestWithValidator( "TimestampHas9FractionalDigits", RECOMMENDED, R"({"optionalTimestamp": "1970-01-01T00:00:00.000000010Z"})", [](const Json::Value& value) { return value["optionalTimestamp"].asString() == "1970-01-01T00:00:00.000000010Z"; - }, - true); + }); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldMask() { +template +void BinaryAndJsonConformanceSuiteImpl< + MessageType>::RunJsonTestsForFieldMask() { RunValidJsonTest("FieldMask", REQUIRED, R"({"optionalFieldMask": "foo,barBaz"})", R"(optional_field_mask: {paths: "foo" paths: "bar_baz"})"); @@ -2919,7 +2848,8 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldMask() { R"(optional_field_mask: {paths: "foo__bar"})"); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForStruct() { +template +void BinaryAndJsonConformanceSuiteImpl::RunJsonTestsForStruct() { RunValidJsonTest("Struct", REQUIRED, R"({ "optionalStruct": { @@ -2931,44 +2861,44 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForStruct() { "listValue": [1234, "5678"], "objectValue": { "value": 0 - } - } + } + } })", R"( optional_struct: { fields: { key: "nullValue" value: {null_value: NULL_VALUE} - } + } fields: { key: "intValue" value: {number_value: 1234} - } + } fields: { key: "boolValue" value: {bool_value: true} - } + } fields: { key: "doubleValue" value: {number_value: 1234.5678} - } + } fields: { key: "stringValue" value: {string_value: "Hello world!"} - } + } fields: { key: "listValue" value: { list_value: { values: { number_value: 1234 - } + } values: { string_value: "5678" - } - } - } } + } + } + } fields: { key: "objectValue" value: { @@ -2977,18 +2907,18 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForStruct() { key: "value" value: { number_value: 0 - } - } - } } } } + } + } + } )"); RunValidJsonTest("StructWithEmptyListValue", REQUIRED, R"({ "optionalStruct": { "listValue": [] - } + } })", R"( optional_struct: { @@ -2996,14 +2926,15 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForStruct() { key: "listValue" value: { list_value: { - } - } - } } + } + } + } )"); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForValue() { +template +void BinaryAndJsonConformanceSuiteImpl::RunJsonTestsForValue() { RunValidJsonTest("ValueAcceptInteger", REQUIRED, R"({"optionalValue": 1})", "optional_value: { number_value: 1}"); RunValidJsonTest("ValueAcceptFloat", REQUIRED, R"({"optionalValue": 1.5})", @@ -3022,12 +2953,12 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForValue() { list_value: { values: { number_value: 0 - } + } values: { string_value: "hello" - } - } - } + } + } + } )"); RunValidJsonTest("ValueAcceptObject", REQUIRED, R"({"optionalValue": {"value": 1}})", @@ -3038,10 +2969,10 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForValue() { key: "value" value: { number_value: 1 - } - } - } } + } + } + } )"); RunValidJsonTest("RepeatedValue", REQUIRED, R"({ @@ -3049,14 +2980,14 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForValue() { })", R"( repeated_value: [ - { + { list_value: { values: [ { string_value: "a"} - ] - } - } ] + } + } + ] )"); RunValidJsonTest("RepeatedListValue", REQUIRED, R"({ @@ -3064,145 +2995,149 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForValue() { })", R"( repeated_list_value: [ - { + { values: [ { string_value: "a"} - ] - } - ] + ] + } + ] )"); RunValidJsonTestWithValidator( "NullValueInOtherOneofOldFormat", RECOMMENDED, - R"({"oneofNullValue": "NULL_VALUE"})", - [](const Json::Value& value) { + R"({"oneofNullValue": "NULL_VALUE"})", [](const Json::Value& value) { return (value.isMember("oneofNullValue") && value["oneofNullValue"].isNull()); - }, - true); + }); RunValidJsonTestWithValidator( "NullValueInOtherOneofNewFormat", RECOMMENDED, - R"({"oneofNullValue": null})", - [](const Json::Value& value) { + R"({"oneofNullValue": null})", [](const Json::Value& value) { return (value.isMember("oneofNullValue") && value["oneofNullValue"].isNull()); - }, - true); + }); RunValidJsonTestWithValidator( "NullValueInNormalMessage", RECOMMENDED, R"({"optionalNullValue": null})", - [](const Json::Value& value) { return value.empty(); }, true); + [](const Json::Value& value) { return value.empty(); }); ExpectSerializeFailureForJson("ValueRejectNanNumberValue", RECOMMENDED, "optional_value: { number_value: nan}"); ExpectSerializeFailureForJson("ValueRejectInfNumberValue", RECOMMENDED, "optional_value: { number_value: inf}"); } -void BinaryAndJsonConformanceSuite::RunJsonTestsForAny() { +template +void BinaryAndJsonConformanceSuiteImpl::RunJsonTestsForAny() { + std::string type_url = GetTypeUrl(MessageType::GetDescriptor()); RunValidJsonTest("Any", REQUIRED, - R"({ + absl::Substitute(R"({ "optionalAny": { - "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", + "@type": "$0", "optionalInt32": 12345 - } + } })", - R"( + GetTypeUrl(MessageType::GetDescriptor())), + absl::Substitute(R"( optional_any: { - [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { + [$0] { optional_int32: 12345 } } - )"); + )", + type_url)); RunValidJsonTest("AnyNested", REQUIRED, - R"({ + absl::Substitute(R"({ "optionalAny": { "@type": "type.googleapis.com/google.protobuf.Any", "value": { - "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3", + "@type": "$0", "optionalInt32": 12345 - } - } + } + } })", - R"( + type_url), + absl::Substitute(R"( optional_any: { [type.googleapis.com/google.protobuf.Any] { - [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { + [$0] { optional_int32: 12345 } } } - )"); + )", + type_url)); // The special "@type" tag is not required to appear first. RunValidJsonTest("AnyUnorderedTypeTag", REQUIRED, - R"({ + absl::Substitute(R"({ "optionalAny": { "optionalInt32": 12345, - "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" + "@type": "$0" } })", - R"( + type_url), + absl::Substitute(R"( optional_any: { - [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { + [$0] { optional_int32: 12345 } } - )"); + )", + type_url)); // Well-known types in Any. RunValidJsonTest("AnyWithInt32ValueWrapper", REQUIRED, R"({ "optionalAny": { "@type": "type.googleapis.com/google.protobuf.Int32Value", "value": 12345 - } + } })", R"( optional_any: { - [type.googleapis.com/google.protobuf.Int32Value] { + [type.googleapis.com/google.protobuf.Int32Value] { value: 12345 - } - } + } + } )"); RunValidJsonTest("AnyWithDuration", REQUIRED, R"({ "optionalAny": { "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.5s" - } + } })", R"( optional_any: { - [type.googleapis.com/google.protobuf.Duration] { + [type.googleapis.com/google.protobuf.Duration] { seconds: 1 nanos: 500000000 - } - } + } + } )"); RunValidJsonTest("AnyWithTimestamp", REQUIRED, R"({ "optionalAny": { "@type": "type.googleapis.com/google.protobuf.Timestamp", "value": "1970-01-01T00:00:00Z" - } + } })", R"( optional_any: { - [type.googleapis.com/google.protobuf.Timestamp] { + [type.googleapis.com/google.protobuf.Timestamp] { seconds: 0 nanos: 0 - } - } + } + } )"); RunValidJsonTest("AnyWithFieldMask", REQUIRED, R"({ "optionalAny": { "@type": "type.googleapis.com/google.protobuf.FieldMask", "value": "foo,barBaz" - } + } })", R"( optional_any: { - [type.googleapis.com/google.protobuf.FieldMask] { + [type.googleapis.com/google.protobuf.FieldMask] { paths: ["foo", "bar_baz"] - } - } + } + } )"); RunValidJsonTest("AnyWithStruct", REQUIRED, R"({ @@ -3210,20 +3145,20 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForAny() { "@type": "type.googleapis.com/google.protobuf.Struct", "value": { "foo": 1 - } - } + } + } })", R"( optional_any: { - [type.googleapis.com/google.protobuf.Struct] { + [type.googleapis.com/google.protobuf.Struct] { fields: { key: "foo" value: { number_value: 1 - } - } - } } + } + } + } )"); RunValidJsonTest("AnyWithValueForJsonObject", REQUIRED, R"({ @@ -3231,38 +3166,126 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForAny() { "@type": "type.googleapis.com/google.protobuf.Value", "value": { "foo": 1 - } - } + } + } })", R"( optional_any: { - [type.googleapis.com/google.protobuf.Value] { + [type.googleapis.com/google.protobuf.Value] { struct_value: { fields: { key: "foo" value: { number_value: 1 - } - } - } } } + } + } + } )"); RunValidJsonTest("AnyWithValueForInteger", REQUIRED, R"({ "optionalAny": { "@type": "type.googleapis.com/google.protobuf.Value", "value": 1 - } + } })", R"( optional_any: { - [type.googleapis.com/google.protobuf.Value] { + [type.googleapis.com/google.protobuf.Value] { number_value: 1 - } - } + } + } )"); } +template +const FieldDescriptor* +BinaryAndJsonConformanceSuiteImpl::GetFieldForType( + FieldDescriptor::Type type, bool repeated, Packed packed) const { + const Descriptor* d = MessageType::GetDescriptor(); + for (int i = 0; i < d->field_count(); i++) { + const FieldDescriptor* f = d->field(i); + if (f->type() == type && f->is_repeated() == repeated) { + if ((packed == Packed::kTrue && !f->is_packed()) || + (packed == Packed::kFalse && f->is_packed())) { + continue; + } + return f; + } + } + + absl::string_view packed_string = ""; + const absl::string_view repeated_string = + repeated ? "Repeated " : "Singular "; + if (packed == Packed::kTrue) { + packed_string = "Packed "; + } + if (packed == Packed::kFalse) { + packed_string = "Unpacked "; + } + ABSL_LOG(FATAL) << "Couldn't find field with type: " << repeated_string + << packed_string << FieldDescriptor::TypeName(type) << " for " + << d->full_name(); + return nullptr; +} + +template +const FieldDescriptor* +BinaryAndJsonConformanceSuiteImpl::GetFieldForMapType( + FieldDescriptor::Type key_type, FieldDescriptor::Type value_type) const { + const Descriptor* d = MessageType::GetDescriptor(); + for (int i = 0; i < d->field_count(); i++) { + const FieldDescriptor* f = d->field(i); + if (f->is_map()) { + const Descriptor* map_entry = f->message_type(); + const FieldDescriptor* key = map_entry->field(0); + const FieldDescriptor* value = map_entry->field(1); + if (key->type() == key_type && value->type() == value_type) { + return f; + } + } + } + + ABSL_LOG(FATAL) << "Couldn't find map field with type: " + << FieldDescriptor::TypeName(key_type) << " and " + << FieldDescriptor::TypeName(key_type) << " for " + << d->full_name(); + return nullptr; +} + +template +const FieldDescriptor* +BinaryAndJsonConformanceSuiteImpl::GetFieldForOneofType( + FieldDescriptor::Type type, bool exclusive) const { + const Descriptor* d = MessageType::GetDescriptor(); + for (int i = 0; i < d->field_count(); i++) { + const FieldDescriptor* f = d->field(i); + if (f->containing_oneof() && ((f->type() == type) ^ exclusive)) { + return f; + } + } + + ABSL_LOG(FATAL) << "Couldn't find oneof field with type: " + << FieldDescriptor::TypeName(type) << " for " + << d->full_name(); + return nullptr; +} + +template +std::string BinaryAndJsonConformanceSuiteImpl::SyntaxIdentifier() + const { + if constexpr (std::is_same::value) { + return "Proto2"; + } else if constexpr (std::is_same::value) { + return "Proto3"; + } else if constexpr (std::is_same::value) { + return "Editions_Proto2"; + } else { + return "Editions_Proto3"; + } +} + } // namespace protobuf } // namespace google diff --git a/conformance/binary_json_conformance_suite.h b/conformance/binary_json_conformance_suite.h index be9579c5fb..d777bba019 100644 --- a/conformance/binary_json_conformance_suite.h +++ b/conformance/binary_json_conformance_suite.h @@ -8,19 +8,58 @@ #ifndef CONFORMANCE_BINARY_JSON_CONFORMANCE_SUITE_H #define CONFORMANCE_BINARY_JSON_CONFORMANCE_SUITE_H +#include +#include +#include +#include +#include + +#include "absl/strings/string_view.h" #include "json/json.h" #include "conformance_test.h" #include "google/protobuf/descriptor.h" +#include "google/protobuf/util/type_resolver.h" namespace google { namespace protobuf { class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { public: - BinaryAndJsonConformanceSuite() {} + BinaryAndJsonConformanceSuite() = default; private: void RunSuiteImpl() override; + bool ParseJsonResponse(const conformance::ConformanceResponse& response, + Message* test_message); + bool ParseResponse(const conformance::ConformanceResponse& response, + const ConformanceRequestSetting& setting, + Message* test_message) override; + void SetTypeUrl(absl::string_view type_url) { + type_url_ = std::string(type_url); + } + + template + friend class BinaryAndJsonConformanceSuiteImpl; + + std::unique_ptr type_resolver_; + std::string type_url_; +}; + +template +class BinaryAndJsonConformanceSuiteImpl { + public: + explicit BinaryAndJsonConformanceSuiteImpl( + BinaryAndJsonConformanceSuite* suite, bool run_proto3_tests); + + private: + using ConformanceRequestSetting = + BinaryAndJsonConformanceSuite::ConformanceRequestSetting; + using ConformanceLevel = BinaryAndJsonConformanceSuite::ConformanceLevel; + constexpr static ConformanceLevel RECOMMENDED = ConformanceLevel::RECOMMENDED; + constexpr static ConformanceLevel REQUIRED = ConformanceLevel::REQUIRED; + + void RunAllTests(); + void RunBinaryPerformanceTests(); void RunJsonPerformanceTests(); void RunJsonTests(); @@ -37,10 +76,6 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { void RunValidJsonTest(const std::string& test_name, ConformanceLevel level, const std::string& input_json, const std::string& equivalent_text_format); - void RunValidJsonTest(const std::string& test_name, ConformanceLevel level, - const std::string& input_json, - const std::string& equivalent_text_format, - bool is_proto3); void RunValidJsonTestWithMessage(const std::string& test_name, ConformanceLevel level, const std::string& input_json, @@ -48,8 +83,7 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { const Message& prototype); void RunValidJsonTestWithProtobufInput( const std::string& test_name, ConformanceLevel level, - const protobuf_test_messages::proto3::TestAllTypesProto3& input, - const std::string& equivalent_text_format); + const MessageType& input, const std::string& equivalent_text_format); void RunValidJsonIgnoreUnknownTest(const std::string& test_name, ConformanceLevel level, const std::string& input_json, @@ -57,38 +91,26 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { void RunValidProtobufTest(const std::string& test_name, ConformanceLevel level, const std::string& input_protobuf, - const std::string& equivalent_text_format, - bool is_proto3); + const std::string& equivalent_text_format); void RunValidBinaryProtobufTest(const std::string& test_name, ConformanceLevel level, - const std::string& input_protobuf, - bool is_proto3); + const std::string& input_protobuf); void RunValidBinaryProtobufTest(const std::string& test_name, ConformanceLevel level, const std::string& input_protobuf, - const std::string& expected_protobuf, - bool is_proto3); - void RunBinaryPerformanceMergeMessageWithField(const std::string& test_name, - const std::string& field_proto, - bool is_proto3); + const std::string& expected_protobuf); + void RunBinaryPerformanceMergeMessageWithField( + const std::string& test_name, const std::string& field_proto); void RunValidProtobufTestWithMessage( const std::string& test_name, ConformanceLevel level, - const Message* input, const std::string& equivalent_text_format, - bool is_proto3); - - bool ParseJsonResponse(const conformance::ConformanceResponse& response, - Message* test_message); - bool ParseResponse(const conformance::ConformanceResponse& response, - const ConformanceRequestSetting& setting, - Message* test_message) override; + const Message* input, const std::string& equivalent_text_format); typedef std::function Validator; void RunValidJsonTestWithValidator(const std::string& test_name, ConformanceLevel level, const std::string& input_json, - const Validator& validator, - bool is_proto3); + const Validator& validator); void ExpectParseFailureForJson(const std::string& test_name, ConformanceLevel level, const std::string& input_json); @@ -97,8 +119,7 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { const std::string& text_format); void ExpectParseFailureForProtoWithProtoVersion(const std::string& proto, const std::string& test_name, - ConformanceLevel level, - bool is_proto3); + ConformanceLevel level); void ExpectParseFailureForProto(const std::string& proto, const std::string& test_name, ConformanceLevel level); @@ -107,10 +128,8 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { ConformanceLevel level); void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type); void TestIllegalTags(); - template - void TestOneofMessage(MessageType& message, bool is_proto3); - template - void TestUnknownMessage(MessageType& message, bool is_proto3); + void TestOneofMessage(); + void TestUnknownMessage(); void TestValidDataForType( google::protobuf::FieldDescriptor::Type, std::vector> values); @@ -128,8 +147,22 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite { void TestJsonPerformanceMergeMessageWithRepeatedFieldForType( google::protobuf::FieldDescriptor::Type, std::string field_value); - std::unique_ptr type_resolver_; - std::string type_url_; + enum class Packed { + kUnspecified = 0, + kTrue = 1, + kFalse = 2, + }; + const FieldDescriptor* GetFieldForType( + FieldDescriptor::Type type, bool repeated, + Packed packed = Packed::kUnspecified) const; + const FieldDescriptor* GetFieldForMapType( + FieldDescriptor::Type key_type, FieldDescriptor::Type value_type) const; + const FieldDescriptor* GetFieldForOneofType(FieldDescriptor::Type type, + bool exclusive = false) const; + std::string SyntaxIdentifier() const; + + BinaryAndJsonConformanceSuite& suite_; + bool run_proto3_tests_; }; } // namespace protobuf diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc index 30baafca22..86c651c0fb 100644 --- a/conformance/conformance_cpp.cc +++ b/conformance/conformance_cpp.cc @@ -21,6 +21,8 @@ #include "absl/status/statusor.h" #include "conformance/conformance.pb.h" #include "conformance/conformance.pb.h" +#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h" +#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h" #include "google/protobuf/endian.h" #include "google/protobuf/message.h" #include "google/protobuf/test_messages_proto2.pb.h" @@ -45,6 +47,10 @@ using ::google::protobuf::util::NewTypeResolverForDescriptorPool; using ::google::protobuf::util::TypeResolver; using ::protobuf_test_messages::proto2::TestAllTypesProto2; using ::protobuf_test_messages::proto3::TestAllTypesProto3; +using TestAllTypesProto2Editions = + ::protobuf_test_messages::editions::proto2::TestAllTypesProto2; +using TestAllTypesProto3Editions = + ::protobuf_test_messages::editions::proto3::TestAllTypesProto3; absl::Status ReadFd(int fd, char* buf, size_t len) { while (len > 0) { @@ -76,6 +82,8 @@ class Harness { Harness() { google::protobuf::LinkMessageReflection(); google::protobuf::LinkMessageReflection(); + google::protobuf::LinkMessageReflection(); + google::protobuf::LinkMessageReflection(); resolver_.reset(NewTypeResolverForDescriptorPool( "type.googleapis.com", DescriptorPool::generated_pool())); diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc index 88cfdc2ad8..dbcaf45836 100644 --- a/conformance/conformance_test.cc +++ b/conformance/conformance_test.cc @@ -9,12 +9,15 @@ #include +#include +#include #include +#include #include #include "google/protobuf/util/field_comparator.h" -#include "google/protobuf/util/json_util.h" #include "google/protobuf/util/message_differencer.h" +#include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" @@ -28,15 +31,14 @@ using conformance::ConformanceRequest; using conformance::ConformanceResponse; using conformance::WireFormat; -using google::protobuf::TextFormat; using google::protobuf::util::DefaultFieldComparator; using google::protobuf::util::MessageDifferencer; using std::string; namespace { -static string ToOctString(const string& binary_string) { - string oct_string; +static std::string ToOctString(const std::string& binary_string) { + std::string oct_string; for (size_t i = 0; i < binary_string.size(); i++) { uint8_t c = binary_string.at(i); uint8_t high = c / 64; @@ -96,7 +98,7 @@ ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting( ConformanceLevel level, conformance::WireFormat input_format, conformance::WireFormat output_format, conformance::TestCategory test_category, const Message& prototype_message, - const string& test_name, const string& input) + const std::string& test_name, const std::string& input) : level_(level), input_format_(input_format), output_format_(output_format), @@ -139,26 +141,37 @@ ConformanceTestSuite::ConformanceRequestSetting::NewTestMessage() const { return std::unique_ptr(prototype_message_for_compare_->New()); } -string ConformanceTestSuite::ConformanceRequestSetting::GetTestName() const { - string rname; +std::string +ConformanceTestSuite::ConformanceRequestSetting::GetSyntaxIdentifier() const { switch (FileDescriptorLegacy(prototype_message_.GetDescriptor()->file()) .syntax()) { case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3: - rname = ".Proto3."; - break; + return "Proto3"; case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2: - rname = ".Proto2."; - break; + return "Proto2"; + case FileDescriptorLegacy::Syntax::SYNTAX_EDITIONS: { + std::string id = "Editions"; + if (prototype_message_.GetDescriptor()->name() == "TestAllTypesProto2") { + absl::StrAppend(&id, "_Proto2"); + } else if (prototype_message_.GetDescriptor()->name() == + "TestAllTypesProto3") { + absl::StrAppend(&id, "_Proto3"); + } + return id; + } default: - break; + return "Unknown"; } +} - return absl::StrCat(ConformanceLevelToString(level_), rname, +string ConformanceTestSuite::ConformanceRequestSetting::GetTestName() const { + return absl::StrCat(ConformanceLevelToString(level_), ".", + GetSyntaxIdentifier(), ".", InputFormatString(input_format_), ".", test_name_, ".", OutputFormatString(output_format_)); } -string +std::string ConformanceTestSuite::ConformanceRequestSetting::ConformanceLevelToString( ConformanceLevel level) const { switch (level) { @@ -171,7 +184,7 @@ ConformanceTestSuite::ConformanceRequestSetting::ConformanceLevelToString( return ""; } -string ConformanceTestSuite::ConformanceRequestSetting::InputFormatString( +std::string ConformanceTestSuite::ConformanceRequestSetting::InputFormatString( conformance::WireFormat format) const { switch (format) { case conformance::PROTOBUF: @@ -186,7 +199,7 @@ string ConformanceTestSuite::ConformanceRequestSetting::InputFormatString( return ""; } -string ConformanceTestSuite::ConformanceRequestSetting::OutputFormatString( +std::string ConformanceTestSuite::ConformanceRequestSetting::OutputFormatString( conformance::WireFormat format) const { switch (format) { case conformance::PROTOBUF: @@ -208,7 +221,7 @@ void ConformanceTestSuite::TruncateDebugPayload(string* payload) { } } -const ConformanceRequest ConformanceTestSuite::TruncateRequest( +ConformanceRequest ConformanceTestSuite::TruncateRequest( const ConformanceRequest& request) { ConformanceRequest debug_request(request); switch (debug_request.payload_case()) { @@ -231,7 +244,7 @@ const ConformanceRequest ConformanceTestSuite::TruncateRequest( return debug_request; } -const ConformanceResponse ConformanceTestSuite::TruncateResponse( +ConformanceResponse ConformanceTestSuite::TruncateResponse( const ConformanceResponse& response) { ConformanceResponse debug_response(response); switch (debug_response.result_case()) { @@ -254,7 +267,7 @@ const ConformanceResponse ConformanceTestSuite::TruncateResponse( return debug_response; } -void ConformanceTestSuite::ReportSuccess(const string& test_name) { +void ConformanceTestSuite::ReportSuccess(const std::string& test_name) { if (expected_to_fail_.erase(test_name) != 0) { absl::StrAppendFormat( &output_, @@ -266,7 +279,7 @@ void ConformanceTestSuite::ReportSuccess(const string& test_name) { successes_++; } -void ConformanceTestSuite::ReportFailure(const string& test_name, +void ConformanceTestSuite::ReportFailure(const std::string& test_name, ConformanceLevel level, const ConformanceRequest& request, const ConformanceResponse& response, @@ -286,7 +299,7 @@ void ConformanceTestSuite::ReportFailure(const string& test_name, TruncateResponse(response).ShortDebugString()); } -void ConformanceTestSuite::ReportSkip(const string& test_name, +void ConformanceTestSuite::ReportSkip(const std::string& test_name, const ConformanceRequest& request, const ConformanceResponse& response) { if (verbose_) { @@ -299,19 +312,20 @@ void ConformanceTestSuite::ReportSkip(const string& test_name, void ConformanceTestSuite::RunValidInputTest( const ConformanceRequestSetting& setting, - const string& equivalent_text_format) { + const std::string& equivalent_text_format) { std::unique_ptr reference_message(setting.NewTestMessage()); ABSL_CHECK(TextFormat::ParseFromString(equivalent_text_format, reference_message.get())) << "Failed to parse data for test case: " << setting.GetTestName() << ", data: " << equivalent_text_format; - const string equivalent_wire_format = reference_message->SerializeAsString(); + const std::string equivalent_wire_format = + reference_message->SerializeAsString(); RunValidBinaryInputTest(setting, equivalent_wire_format); } void ConformanceTestSuite::RunValidBinaryInputTest( const ConformanceRequestSetting& setting, - const string& equivalent_wire_format, bool require_same_wire_format) { + const std::string& equivalent_wire_format, bool require_same_wire_format) { const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; RunTest(setting.GetTestName(), request, &response); @@ -321,11 +335,12 @@ void ConformanceTestSuite::RunValidBinaryInputTest( void ConformanceTestSuite::VerifyResponse( const ConformanceRequestSetting& setting, - const string& equivalent_wire_format, const ConformanceResponse& response, - bool need_report_success, bool require_same_wire_format) { + const std::string& equivalent_wire_format, + const ConformanceResponse& response, bool need_report_success, + bool require_same_wire_format) { std::unique_ptr test_message(setting.NewTestMessage()); const ConformanceRequest& request = setting.GetRequest(); - const string& test_name = setting.GetTestName(); + const std::string& test_name = setting.GetTestName(); ConformanceLevel level = setting.GetLevel(); std::unique_ptr reference_message = setting.NewTestMessage(); @@ -358,7 +373,7 @@ void ConformanceTestSuite::VerifyResponse( DefaultFieldComparator field_comparator; field_comparator.set_treat_nan_as_equal(true); differencer.set_field_comparator(&field_comparator); - string differences; + std::string differences; differencer.ReportDifferencesToString(&differences); bool check = false; @@ -366,7 +381,7 @@ void ConformanceTestSuite::VerifyResponse( if (require_same_wire_format) { ABSL_DCHECK_EQ(response.result_case(), ConformanceResponse::kProtobufPayload); - const string& protobuf_payload = response.protobuf_payload(); + const std::string& protobuf_payload = response.protobuf_payload(); check = equivalent_wire_format == protobuf_payload; differences = absl::StrCat("Expect: ", ToOctString(equivalent_wire_format), ", but got: ", ToOctString(protobuf_payload)); @@ -386,15 +401,15 @@ void ConformanceTestSuite::VerifyResponse( } } -void ConformanceTestSuite::RunTest(const string& test_name, +void ConformanceTestSuite::RunTest(const std::string& test_name, const ConformanceRequest& request, ConformanceResponse* response) { if (test_names_.insert(test_name).second == false) { ABSL_LOG(FATAL) << "Duplicated test name: " << test_name; } - string serialized_request; - string serialized_response; + std::string serialized_request; + std::string serialized_response; request.SerializeToString(&serialized_request); runner_->RunTest(test_name, serialized_request, &serialized_response); @@ -412,7 +427,7 @@ void ConformanceTestSuite::RunTest(const string& test_name, } } -string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) { +std::string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) { switch (wire_format) { case conformance::PROTOBUF: return "PROTOBUF"; @@ -435,7 +450,8 @@ void ConformanceTestSuite::AddExpectedFailedTest(const std::string& test_name) { } bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, - std::string* output, const string& filename, + std::string* output, + const std::string& filename, conformance::FailureSet* failure_list) { runner_ = runner; successes_ = 0; @@ -449,7 +465,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, failure_list_filename_ = filename; expected_to_fail_.clear(); - for (const string& failure : failure_list->failure()) { + for (const std::string& failure : failure_list->failure()) { AddExpectedFailedTest(failure); } RunSuiteImpl(); diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h index 0e3fb704ac..c78f9ea8ab 100644 --- a/conformance/conformance_test.h +++ b/conformance/conformance_test.h @@ -14,13 +14,16 @@ #ifndef CONFORMANCE_CONFORMANCE_TEST_H #define CONFORMANCE_CONFORMANCE_TEST_H -#include +#include +#include #include #include +#include "google/protobuf/descriptor.pb.h" #include "google/protobuf/util/type_resolver.h" #include "absl/container/btree_set.h" #include "absl/container/flat_hash_set.h" +#include "absl/strings/string_view.h" #include "conformance/conformance.pb.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/wire_format_lite.h" @@ -129,6 +132,7 @@ class ConformanceTestSuite { : verbose_(false), performance_(false), enforce_recommended_(false), + maximum_edition_(Edition::EDITION_PROTO3), failure_list_flag_name_("--failure_list") {} virtual ~ConformanceTestSuite() {} @@ -145,6 +149,9 @@ class ConformanceTestSuite { // difference between REQUIRED and RECOMMENDED test cases. void SetEnforceRecommended(bool value) { enforce_recommended_ = value; } + // Sets the maximum edition (inclusive) that should be tests for conformance. + void SetMaximumEdition(Edition edition) { maximum_edition_ = edition; } + // Gets the flag name to the failure list file. // By default, this would return --failure_list std::string GetFailureListFlagName() { return failure_list_flag_name_; } @@ -198,13 +205,15 @@ class ConformanceTestSuite { std::unique_ptr NewTestMessage() const; + std::string GetSyntaxIdentifier() const; + std::string GetTestName() const; const conformance::ConformanceRequest& GetRequest() const { return request_; } - const ConformanceLevel GetLevel() const { return level_; } + ConformanceLevel GetLevel() const { return level_; } std::string ConformanceLevelToString(ConformanceLevel level) const; @@ -245,9 +254,9 @@ class ConformanceTestSuite { bool need_report_success, bool require_same_wire_format); void TruncateDebugPayload(std::string* payload); - const conformance::ConformanceRequest TruncateRequest( + conformance::ConformanceRequest TruncateRequest( const conformance::ConformanceRequest& request); - const conformance::ConformanceResponse TruncateResponse( + conformance::ConformanceResponse TruncateResponse( const conformance::ConformanceResponse& response); void ReportSuccess(const std::string& test_name); @@ -279,6 +288,7 @@ class ConformanceTestSuite { bool verbose_; bool performance_; bool enforce_recommended_; + Edition maximum_edition_; std::string output_; std::string output_dir_; std::string failure_list_flag_name_; diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc index 44b9a09f5a..5edb3c651e 100644 --- a/conformance/conformance_test_runner.cc +++ b/conformance/conformance_test_runner.cc @@ -37,12 +37,15 @@ #include #include +#include #include +#include #include #include #include #include "absl/log/absl_log.h" +#include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "conformance/conformance.pb.h" #include "conformance_test.h" @@ -119,6 +122,11 @@ void UsageError() { fprintf(stderr, " strictly conforming to protobuf\n"); fprintf(stderr, " spec.\n"); + fprintf(stderr, + " --maximum edition Only run conformance tests up to \n"); + fprintf(stderr, + " and including the specified\n"); + fprintf(stderr, " edition.\n"); fprintf(stderr, " --output_dir Directory to write\n" " output files.\n"); @@ -200,6 +208,14 @@ int ForkPipeRunner::Run(int argc, char *argv[], suite->SetVerbose(true); } else if (strcmp(argv[arg], "--enforce_recommended") == 0) { suite->SetEnforceRecommended(true); + } else if (strcmp(argv[arg], "--maximum_edition") == 0) { + if (++arg == argc) UsageError(); + Edition edition = EDITION_UNKNOWN; + if (!Edition_Parse(absl::StrCat("EDITION_", argv[arg]), &edition)) { + fprintf(stderr, "Unknown edition: %s\n", argv[arg]); + UsageError(); + } + suite->SetMaximumEdition(edition); } else if (strcmp(argv[arg], "--output_dir") == 0) { if (++arg == argc) UsageError(); suite->SetOutputDir(argv[arg]); diff --git a/conformance/defs.bzl b/conformance/defs.bzl index 8daef8650c..3a7d1d6cbc 100644 --- a/conformance/defs.bzl +++ b/conformance/defs.bzl @@ -8,6 +8,7 @@ def conformance_test( testee, failure_list = None, text_format_failure_list = None, + maximum_edition = None, **kwargs): """Conformance test runner. @@ -27,6 +28,8 @@ def conformance_test( if text_format_failure_list: args = args + ["--text_format_failure_list %s" % _strip_bazel(text_format_failure_list)] failure_lists = failure_lists + [text_format_failure_list] + if maximum_edition: + args = args + ["--maximum_edition %s" % maximum_edition] native.sh_test( name = name, diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt index aa18cea1a6..235ae697b8 100644 --- a/conformance/failure_list_cpp.txt +++ b/conformance/failure_list_cpp.txt @@ -7,30 +7,57 @@ # TODO: insert links to corresponding bugs tracking the issue. # Should we use GitHub issues or the Google-internal bug tracker? -Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.FieldMaskTooManyUnderscore.JsonOutput +Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput +Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput +Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput +Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput +Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput +Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse +Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue +Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter +Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter Recommended.Proto3.JsonInput.FieldNameDuplicate +Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing1 +Recommended.Editions_Proto3.JsonInput.FieldNameDuplicateDifferentCasing1 Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing2 +Recommended.Editions_Proto3.JsonInput.FieldNameDuplicateDifferentCasing2 Recommended.Proto3.JsonInput.FieldNameNotQuoted +Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput +Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput Recommended.Proto3.JsonInput.MapFieldValueIsNull +Recommended.Editions_Proto3.JsonInput.MapFieldValueIsNull Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull +Recommended.Editions_Proto3.JsonInput.RepeatedFieldMessageElementIsNull Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull +Recommended.Editions_Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull Recommended.Proto3.JsonInput.RepeatedFieldTrailingComma +Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingComma Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines +Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace +Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace +Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth +Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey +Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue +Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue Recommended.Proto3.JsonInput.StringFieldUppercaseEscapeLetter +Recommended.Editions_Proto3.JsonInput.StringFieldUppercaseEscapeLetter Recommended.Proto3.JsonInput.TrailingCommaInAnObject +Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObject Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines +Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpace +Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithSpace Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace +Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace Recommended.Proto2.JsonInput.FieldNameExtension.Validator +Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt index 6999ff0755..6c7c0dd029 100644 --- a/conformance/failure_list_csharp.txt +++ b/conformance/failure_list_csharp.txt @@ -5,5 +5,5 @@ Required.Proto3.JsonInput.OneofFieldNullFirst.JsonOutput Required.Proto3.JsonInput.OneofFieldNullFirst.ProtobufOutput Required.Proto3.JsonInput.OneofFieldNullSecond.JsonOutput Required.Proto3.JsonInput.OneofFieldNullSecond.ProtobufOutput -Recommended.ValueRejectInfNumberValue.JsonOutput -Recommended.ValueRejectNanNumberValue.JsonOutput \ No newline at end of file +Recommended.Proto3.ValueRejectInfNumberValue.JsonOutput +Recommended.Proto3.ValueRejectNanNumberValue.JsonOutput diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt index 808e230eba..8508abd31d 100644 --- a/conformance/failure_list_java.txt +++ b/conformance/failure_list_java.txt @@ -4,9 +4,9 @@ # By listing them here we can keep tabs on which ones are failing and be sure # that we don't introduce regressions in other tests. -Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.FieldMaskTooManyUnderscore.JsonOutput +Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput +Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput +Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse diff --git a/conformance/failure_list_jruby.txt b/conformance/failure_list_jruby.txt index c0d29804fe..6d511a38a6 100644 --- a/conformance/failure_list_jruby.txt +++ b/conformance/failure_list_jruby.txt @@ -1,6 +1,6 @@ -Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.FieldMaskTooManyUnderscore.JsonOutput +Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput +Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput +Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput Recommended.Proto2.JsonInput.FieldNameExtension.Validator Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue diff --git a/conformance/text_format_conformance_suite.cc b/conformance/text_format_conformance_suite.cc index 25740ee9b4..1c2c17bdbe 100644 --- a/conformance/text_format_conformance_suite.cc +++ b/conformance/text_format_conformance_suite.cc @@ -7,25 +7,30 @@ #include "text_format_conformance_suite.h" -#include "google/protobuf/any.pb.h" +#include +#include +#include + #include "absl/log/absl_log.h" +#include "absl/log/die_if_null.h" #include "absl/strings/str_cat.h" #include "conformance_test.h" +#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h" +#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h" #include "google/protobuf/test_messages_proto2.pb.h" #include "google/protobuf/test_messages_proto3.pb.h" #include "google/protobuf/text_format.h" -namespace proto2_messages = protobuf_test_messages::proto2; - using conformance::ConformanceRequest; using conformance::ConformanceResponse; using conformance::WireFormat; -using google::protobuf::Message; -using google::protobuf::TextFormat; -using proto2_messages::TestAllTypesProto2; -using proto2_messages::UnknownToTestAllTypes; +using protobuf_test_messages::proto2::TestAllTypesProto2; +using protobuf_test_messages::proto2::UnknownToTestAllTypes; using protobuf_test_messages::proto3::TestAllTypesProto3; -using std::string; +using TestAllTypesProto2Editions = + protobuf_test_messages::editions::proto2::TestAllTypesProto2; +using TestAllTypesProto3Editions = + protobuf_test_messages::editions::proto3::TestAllTypesProto3; namespace google { namespace protobuf { @@ -61,7 +66,7 @@ bool TextFormatConformanceTestSuite::ParseResponse( const ConformanceRequestSetting& setting, Message* test_message) { const ConformanceRequest& request = setting.GetRequest(); WireFormat requested_output = request.requested_output_format(); - const string& test_name = setting.GetTestName(); + const std::string& test_name = setting.GetTestName(); ConformanceLevel level = setting.GetLevel(); switch (response.result_case()) { @@ -111,10 +116,39 @@ bool TextFormatConformanceTestSuite::ParseResponse( return true; } -void TextFormatConformanceTestSuite::ExpectParseFailure(const string& test_name, - ConformanceLevel level, - const string& input) { - TestAllTypesProto3 prototype; +void TextFormatConformanceTestSuite::RunSuiteImpl() { + TextFormatConformanceTestSuiteImpl(this); + TextFormatConformanceTestSuiteImpl(this); + if (maximum_edition_ >= Edition::EDITION_2023) { + TextFormatConformanceTestSuiteImpl(this); + TextFormatConformanceTestSuiteImpl(this); + } +} + +template +TextFormatConformanceTestSuiteImpl:: + TextFormatConformanceTestSuiteImpl(TextFormatConformanceTestSuite* suite) + : suite_(*ABSL_DIE_IF_NULL(suite)) { + // Flag control performance tests to keep them internal and opt-in only + if (suite_.performance_) { + RunTextFormatPerformanceTests(); + } else { + if (MessageType::GetDescriptor()->name() == "TestAllTypesProto2") { + RunGroupTests(); + } + if (MessageType::GetDescriptor()->name() == "TestAllTypesProto3") { + RunAnyTests(); + // TODO Run these over proto2 also. + RunAllTests(); + } + } +} + +template +void TextFormatConformanceTestSuiteImpl::ExpectParseFailure( + const std::string& test_name, ConformanceLevel level, + const std::string& input) { + MessageType prototype; // We don't expect output, but if the program erroneously accepts the protobuf // we let it send its response as this. We must not leave it unspecified. ConformanceRequestSetting setting( @@ -122,86 +156,75 @@ void TextFormatConformanceTestSuite::ExpectParseFailure(const string& test_name, conformance::TEXT_FORMAT_TEST, prototype, test_name, input); const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; - string effective_test_name = - absl::StrCat(setting.ConformanceLevelToString(level), - ".Proto3.TextFormatInput.", test_name); + std::string effective_test_name = absl::StrCat( + setting.ConformanceLevelToString(level), ".", + setting.GetSyntaxIdentifier(), ".TextFormatInput.", test_name); - RunTest(effective_test_name, request, &response); + suite_.RunTest(effective_test_name, request, &response); if (response.result_case() == ConformanceResponse::kParseError) { - ReportSuccess(effective_test_name); + suite_.ReportSuccess(effective_test_name); } else if (response.result_case() == ConformanceResponse::kSkipped) { - ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(effective_test_name, request, response); } else { - ReportFailure(effective_test_name, level, request, response, - "Should have failed to parse, but didn't."); + suite_.ReportFailure(effective_test_name, level, request, response, + "Should have failed to parse, but didn't."); } } -void TextFormatConformanceTestSuite::RunValidTextFormatTest( - const string& test_name, ConformanceLevel level, const string& input_text) { - TestAllTypesProto3 prototype; +template +void TextFormatConformanceTestSuiteImpl::RunValidTextFormatTest( + const std::string& test_name, ConformanceLevel level, + const std::string& input_text) { + MessageType prototype; RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype); } -void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2( - const string& test_name, ConformanceLevel level, const string& input_text) { - TestAllTypesProto2 prototype; - RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype); -} - -void TextFormatConformanceTestSuite::RunValidTextFormatTestWithExpected( - const string& test_name, ConformanceLevel level, const string& input_text, - const string& expected_text) { - TestAllTypesProto3 prototype; - RunValidTextFormatTestWithMessage(test_name, level, input_text, expected_text, - prototype); -} - -void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2WithExpected( - const string& test_name, ConformanceLevel level, const string& input_text, - const string& expected_text) { - TestAllTypesProto2 prototype; - RunValidTextFormatTestWithMessage(test_name, level, input_text, expected_text, - prototype); -} - -void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage( - const string& test_name, ConformanceLevel level, const string& input_text, - const Message& prototype) { +template +void TextFormatConformanceTestSuiteImpl:: + RunValidTextFormatTestWithMessage(const std::string& test_name, + ConformanceLevel level, + const std::string& input_text, + const Message& message) { ConformanceRequestSetting setting1( level, conformance::TEXT_FORMAT, conformance::PROTOBUF, - conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); - RunValidInputTest(setting1, input_text); + conformance::TEXT_FORMAT_TEST, message, test_name, input_text); + suite_.RunValidInputTest(setting1, input_text); ConformanceRequestSetting setting2( level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT, - conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); - RunValidInputTest(setting2, input_text); + conformance::TEXT_FORMAT_TEST, message, test_name, input_text); + suite_.RunValidInputTest(setting2, input_text); } -void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage( - const string& test_name, ConformanceLevel level, const string& input_text, - const string& expected_text, const Message& prototype) { +template +void TextFormatConformanceTestSuiteImpl:: + RunValidTextFormatTestWithExpected(const std::string& test_name, + ConformanceLevel level, + const std::string& input_text, + const std::string& expected_text) { + MessageType prototype; ConformanceRequestSetting setting1( level, conformance::TEXT_FORMAT, conformance::PROTOBUF, conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); - RunValidInputTest(setting1, expected_text); + suite_.RunValidInputTest(setting1, expected_text); ConformanceRequestSetting setting2( level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text); - RunValidInputTest(setting2, expected_text); + suite_.RunValidInputTest(setting2, expected_text); } -void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest( - const string& test_name, const Message& message) { - string serialized_input; +template +void TextFormatConformanceTestSuiteImpl< + MessageType>::RunValidUnknownTextFormatTest(const std::string& test_name, + const Message& message) { + std::string serialized_input; message.SerializeToString(&serialized_input); - TestAllTypesProto3 prototype; + MessageType prototype; ConformanceRequestSetting setting1( RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT_TEST, prototype, absl::StrCat(test_name, "_Drop"), serialized_input); setting1.SetPrototypeMessageForCompare(message); - RunValidBinaryInputTest(setting1, ""); + suite_.RunValidBinaryInputTest(setting1, ""); ConformanceRequestSetting setting2( RECOMMENDED, conformance::PROTOBUF, conformance::TEXT_FORMAT, @@ -209,207 +232,182 @@ void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest( absl::StrCat(test_name, "_Print"), serialized_input); setting2.SetPrototypeMessageForCompare(message); setting2.SetPrintUnknownFields(true); - RunValidBinaryInputTest(setting2, serialized_input); + suite_.RunValidBinaryInputTest(setting2, serialized_input); } -void TextFormatConformanceTestSuite::RunSuiteImpl() { - if (!performance_) { - RunValidTextFormatTest("HelloWorld", REQUIRED, - "optional_string: 'Hello, World!'"); - // Integer fields. - RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED, - "optional_int32: 2147483647"); - RunValidTextFormatTest("Int32FieldMinValue", REQUIRED, - "optional_int32: -2147483648"); - RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED, - "optional_uint32: 4294967295"); - RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED, - "optional_int64: 9223372036854775807"); - RunValidTextFormatTest("Int64FieldMinValue", REQUIRED, - "optional_int64: -9223372036854775808"); - RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED, - "optional_uint64: 18446744073709551615"); - - // Parsers reject out-of-bound integer values. - ExpectParseFailure("Int32FieldTooLarge", REQUIRED, - "optional_int32: 2147483648"); - ExpectParseFailure("Int32FieldTooSmall", REQUIRED, - "optional_int32: -2147483649"); - ExpectParseFailure("Uint32FieldTooLarge", REQUIRED, - "optional_uint32: 4294967296"); - ExpectParseFailure("Int64FieldTooLarge", REQUIRED, - "optional_int64: 9223372036854775808"); - ExpectParseFailure("Int64FieldTooSmall", REQUIRED, - "optional_int64: -9223372036854775809"); - ExpectParseFailure("Uint64FieldTooLarge", REQUIRED, - "optional_uint64: 18446744073709551616"); - - // Floating point fields - RunValidTextFormatTest("FloatField", REQUIRED, "optional_float: 3.192837"); - RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED, - "optional_float: 3.123456789123456789"); - RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED, - "optional_float: 3.4028235e+38"); - RunValidTextFormatTest("FloatFieldMinValue", REQUIRED, - "optional_float: 1.17549e-38"); - RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED, - "optional_float: NaN"); - RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED, - "optional_float: inf"); - RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED, - "optional_float: -inf"); - RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED, - "optional_float: 4294967296"); - RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED, - "optional_float: 9223372036854775808"); - RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED, - "optional_float: 3.4028235e+39"); - RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED, - "optional_float: 1.17549e-39"); - RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED, - "optional_float: 18446744073709551616"); - - // String literals x {Strings, Bytes} - for (const auto& field_type : std::vector{"String", "Bytes"}) { - const std::string field_name = - field_type == "String" ? "optional_string" : "optional_bytes"; - RunValidTextFormatTest( - absl::StrCat("StringLiteralConcat", field_type), REQUIRED, - absl::StrCat(field_name, ": 'first' \"second\"\n'third'")); - RunValidTextFormatTest( - absl::StrCat("StringLiteralBasicEscapes", field_type), REQUIRED, - absl::StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'")); - RunValidTextFormatTest( - absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED, - absl::StrCat(field_name, ": '\\341\\210\\264'")); - RunValidTextFormatTest( - absl::StrCat("StringLiteralHexEscapes", field_type), REQUIRED, - absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'")); - RunValidTextFormatTest( - absl::StrCat("StringLiteralShortUnicodeEscape", field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\u1234'")); - RunValidTextFormatTest( - absl::StrCat("StringLiteralLongUnicodeEscapes", field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'")); - // String literals don't include line feeds. - ExpectParseFailure( - absl::StrCat("StringLiteralIncludesLF", field_type), REQUIRED, - absl::StrCat(field_name, ": 'first line\nsecond line'")); - // Unicode escapes don't include code points that lie beyond the planes - // (> 0x10ffff). - ExpectParseFailure( - absl::StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type), - REQUIRED, absl::StrCat(field_name, ": '\\U00110000'")); - // Unicode escapes don't include surrogates. - ExpectParseFailure( - absl::StrCat("StringLiteralShortUnicodeEscapeSurrogatePair", - field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\udc37'")); - ExpectParseFailure( - absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly", - field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\ud800'")); - ExpectParseFailure( - absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly", - field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\udc00'")); - ExpectParseFailure( - absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly", - field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d800'")); - ExpectParseFailure( - absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly", - field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'")); - ExpectParseFailure( - absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", - field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'")); - ExpectParseFailure( - absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort", - field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\udc37'")); - ExpectParseFailure( - absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong", - field_type), - RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\U0000dc37'")); - - // The following method depend on the type of field, as strings have extra - // validation. - const auto test_method = - field_type == "String" - ? &TextFormatConformanceTestSuite::ExpectParseFailure - : &TextFormatConformanceTestSuite::RunValidTextFormatTest; - - // String fields reject invalid UTF-8 byte sequences; bytes fields don't. - (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Octal"), - REQUIRED, absl::StrCat(field_name, ": '\\300'")); - (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Hex"), - REQUIRED, absl::StrCat(field_name, ": '\\xc0'")); - } +template +void TextFormatConformanceTestSuiteImpl::RunGroupTests() { + RunValidTextFormatTest("GroupFieldNoColon", REQUIRED, + "Data { group_int32: 1 }"); + RunValidTextFormatTest("GroupFieldWithColon", REQUIRED, + "Data: { group_int32: 1 }"); + RunValidTextFormatTest("GroupFieldEmpty", REQUIRED, "Data {}"); +} - // Group fields - RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED, - "Data { group_int32: 1 }"); - RunValidTextFormatTestProto2("GroupFieldWithColon", REQUIRED, - "Data: { group_int32: 1 }"); - RunValidTextFormatTestProto2("GroupFieldEmpty", REQUIRED, "Data {}"); - - // Unknown Fields - UnknownToTestAllTypes message; - // Unable to print unknown Fixed32/Fixed64 fields as if they are known. - // Fixed32/Fixed64 fields are not added in the tests. - message.set_optional_int32(123); - message.set_optional_string("hello"); - message.set_optional_bool(true); - RunValidUnknownTextFormatTest("ScalarUnknownFields", message); - - message.Clear(); - message.mutable_nested_message()->set_c(111); - RunValidUnknownTextFormatTest("MessageUnknownFields", message); - - message.Clear(); - message.mutable_optionalgroup()->set_a(321); - RunValidUnknownTextFormatTest("GroupUnknownFields", message); - - message.add_repeated_int32(1); - message.add_repeated_int32(2); - message.add_repeated_int32(3); - RunValidUnknownTextFormatTest("RepeatedUnknownFields", message); - - // Any fields - RunValidTextFormatTest("AnyField", REQUIRED, - R"( - optional_any: { - [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] { - optional_int32: 12345 - } - } - )"); - RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED, - R"( - optional_any: { - type_url: "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" - value: "\b\271`" - } - )"); - ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED, - R"( - optional_any: { - [type.googleapis.com/unknown] { - optional_int32: 12345 - } - } - )"); +template +void TextFormatConformanceTestSuiteImpl::RunAllTests() { + RunValidTextFormatTest("HelloWorld", REQUIRED, + "optional_string: 'Hello, World!'"); + // Integer fields. + RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED, + "optional_int32: 2147483647"); + RunValidTextFormatTest("Int32FieldMinValue", REQUIRED, + "optional_int32: -2147483648"); + RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED, + "optional_uint32: 4294967295"); + RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED, + "optional_int64: 9223372036854775807"); + RunValidTextFormatTest("Int64FieldMinValue", REQUIRED, + "optional_int64: -9223372036854775808"); + RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED, + "optional_uint64: 18446744073709551615"); + + // Parsers reject out-of-bound integer values. + ExpectParseFailure("Int32FieldTooLarge", REQUIRED, + "optional_int32: 2147483648"); + ExpectParseFailure("Int32FieldTooSmall", REQUIRED, + "optional_int32: -2147483649"); + ExpectParseFailure("Uint32FieldTooLarge", REQUIRED, + "optional_uint32: 4294967296"); + ExpectParseFailure("Int64FieldTooLarge", REQUIRED, + "optional_int64: 9223372036854775808"); + ExpectParseFailure("Int64FieldTooSmall", REQUIRED, + "optional_int64: -9223372036854775809"); + ExpectParseFailure("Uint64FieldTooLarge", REQUIRED, + "optional_uint64: 18446744073709551616"); + + // Floating point fields + RunValidTextFormatTest("FloatField", REQUIRED, "optional_float: 3.192837"); + RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED, + "optional_float: 3.123456789123456789"); + RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED, + "optional_float: 3.4028235e+38"); + RunValidTextFormatTest("FloatFieldMinValue", REQUIRED, + "optional_float: 1.17549e-38"); + RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED, "optional_float: NaN"); + RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED, + "optional_float: inf"); + RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED, + "optional_float: -inf"); + RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED, + "optional_float: 4294967296"); + RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED, + "optional_float: 9223372036854775808"); + RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED, + "optional_float: 3.4028235e+39"); + RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED, + "optional_float: 1.17549e-39"); + RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED, + "optional_float: 18446744073709551616"); + + // String literals x {Strings, Bytes} + for (const auto& field_type : std::vector{"String", "Bytes"}) { + const std::string field_name = + field_type == "String" ? "optional_string" : "optional_bytes"; + RunValidTextFormatTest( + absl::StrCat("StringLiteralConcat", field_type), REQUIRED, + absl::StrCat(field_name, ": 'first' \"second\"\n'third'")); + RunValidTextFormatTest( + absl::StrCat("StringLiteralBasicEscapes", field_type), REQUIRED, + absl::StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'")); + RunValidTextFormatTest( + absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED, + absl::StrCat(field_name, ": '\\341\\210\\264'")); + RunValidTextFormatTest(absl::StrCat("StringLiteralHexEscapes", field_type), + REQUIRED, + absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'")); + RunValidTextFormatTest( + absl::StrCat("StringLiteralShortUnicodeEscape", field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\u1234'")); + RunValidTextFormatTest( + absl::StrCat("StringLiteralLongUnicodeEscapes", field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'")); + // String literals don't include line feeds. + ExpectParseFailure(absl::StrCat("StringLiteralIncludesLF", field_type), + REQUIRED, + absl::StrCat(field_name, ": 'first line\nsecond line'")); + // Unicode escapes don't include code points that lie beyond the planes + // (> 0x10ffff). + ExpectParseFailure( + absl::StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type), + REQUIRED, absl::StrCat(field_name, ": '\\U00110000'")); + // Unicode escapes don't include surrogates. + ExpectParseFailure( + absl::StrCat("StringLiteralShortUnicodeEscapeSurrogatePair", + field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\udc37'")); + ExpectParseFailure( + absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly", + field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\ud800'")); + ExpectParseFailure( + absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly", + field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\udc00'")); + ExpectParseFailure( + absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly", + field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d800'")); + ExpectParseFailure( + absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly", + field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'")); + ExpectParseFailure( + absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'")); + ExpectParseFailure( + absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort", + field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\udc37'")); + ExpectParseFailure( + absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong", + field_type), + RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\U0000dc37'")); + + // The following method depend on the type of field, as strings have extra + // validation. + const auto test_method = + field_type == "String" + ? &TextFormatConformanceTestSuiteImpl::ExpectParseFailure + : &TextFormatConformanceTestSuiteImpl::RunValidTextFormatTest; + + // String fields reject invalid UTF-8 byte sequences; bytes fields don't. + (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Octal"), + REQUIRED, absl::StrCat(field_name, ": '\\300'")); + (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Hex"), REQUIRED, + absl::StrCat(field_name, ": '\\xc0'")); + } - // Map fields - TestAllTypesProto3 prototype; - (*prototype.mutable_map_string_string())["c"] = "value"; - (*prototype.mutable_map_string_string())["b"] = "value"; - (*prototype.mutable_map_string_string())["a"] = "value"; - RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys", - REQUIRED, - R"( + // Unknown Fields + UnknownToTestAllTypes message; + // Unable to print unknown Fixed32/Fixed64 fields as if they are known. + // Fixed32/Fixed64 fields are not added in the tests. + message.set_optional_int32(123); + message.set_optional_string("hello"); + message.set_optional_bool(true); + RunValidUnknownTextFormatTest("ScalarUnknownFields", message); + + message.Clear(); + message.mutable_nested_message()->set_c(111); + RunValidUnknownTextFormatTest("MessageUnknownFields", message); + + message.Clear(); + message.mutable_optionalgroup()->set_a(321); + RunValidUnknownTextFormatTest("GroupUnknownFields", message); + + message.add_repeated_int32(1); + message.add_repeated_int32(2); + message.add_repeated_int32(3); + RunValidUnknownTextFormatTest("RepeatedUnknownFields", message); + + // Map fields + MessageType prototype; + (*prototype.mutable_map_string_string())["c"] = "value"; + (*prototype.mutable_map_string_string())["b"] = "value"; + (*prototype.mutable_map_string_string())["a"] = "value"; + RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys", + REQUIRED, + R"( map_string_string { key: "a" value: "value" @@ -423,15 +421,14 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { value: "value" } )", - prototype); - - prototype.Clear(); - (*prototype.mutable_map_int32_int32())[3] = 0; - (*prototype.mutable_map_int32_int32())[2] = 0; - (*prototype.mutable_map_int32_int32())[1] = 0; - RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", - REQUIRED, - R"( + prototype); + + prototype.Clear(); + (*prototype.mutable_map_int32_int32())[3] = 0; + (*prototype.mutable_map_int32_int32())[2] = 0; + (*prototype.mutable_map_int32_int32())[1] = 0; + RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", REQUIRED, + R"( map_int32_int32 { key: 1 value: 0 @@ -445,14 +442,13 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { value: 0 } )", - prototype); - - prototype.Clear(); - (*prototype.mutable_map_bool_bool())[true] = false; - (*prototype.mutable_map_bool_bool())[false] = false; - RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", - REQUIRED, - R"( + prototype); + + prototype.Clear(); + (*prototype.mutable_map_bool_bool())[true] = false; + (*prototype.mutable_map_bool_bool())[false] = false; + RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", REQUIRED, + R"( map_bool_bool { key: false value: false @@ -462,12 +458,12 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { value: false } )", - prototype); + prototype); - prototype.Clear(); - ConformanceRequestSetting setting_map( - REQUIRED, conformance::TEXT_FORMAT, conformance::PROTOBUF, - conformance::TEXT_FORMAT_TEST, prototype, "DuplicateMapKey", R"( + prototype.Clear(); + ConformanceRequestSetting setting_map( + REQUIRED, conformance::TEXT_FORMAT, conformance::PROTOBUF, + conformance::TEXT_FORMAT_TEST, prototype, "DuplicateMapKey", R"( map_string_nested_message { key: "duplicate" value: { a: 123 } @@ -477,21 +473,47 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { value: { corecursive: {} } } )"); - // The last-specified value will be retained in a parsed map - RunValidInputTest(setting_map, R"( + // The last-specified value will be retained in a parsed map + suite_.RunValidInputTest(setting_map, R"( map_string_nested_message { key: "duplicate" value: { corecursive: {} } } )"); - } - // Flag control performance tests to keep them internal and opt-in only - if (performance_) { - RunTextFormatPerformanceTests(); - } } -void TextFormatConformanceTestSuite::RunTextFormatPerformanceTests() { +template +void TextFormatConformanceTestSuiteImpl::RunAnyTests() { + // Any fields + RunValidTextFormatTest("AnyField", REQUIRED, + R"( + optional_any: { + [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] + { optional_int32: 12345 + } + } + )"); + RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED, + R"( + optional_any: { + type_url: + "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3" value: + "\b\271`" + } + )"); + ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED, + R"( + optional_any: { + [type.googleapis.com/unknown] { + optional_int32: 12345 + } + } + )"); +} + +template +void TextFormatConformanceTestSuiteImpl< + MessageType>::RunTextFormatPerformanceTests() { TestTextFormatPerformanceMergeMessageWithRepeatedField("Bool", "repeated_bool: true"); TestTextFormatPerformanceMergeMessageWithRepeatedField( @@ -507,30 +529,27 @@ void TextFormatConformanceTestSuite::RunTextFormatPerformanceTests() { } // This is currently considered valid input by some languages but not others -void TextFormatConformanceTestSuite:: +template +void TextFormatConformanceTestSuiteImpl:: TestTextFormatPerformanceMergeMessageWithRepeatedField( - const string& test_type_name, const string& message_field) { - string recursive_message = + const std::string& test_type_name, const std::string& message_field) { + std::string recursive_message = absl::StrCat("recursive_message { ", message_field, " }"); - string input; + std::string input; for (size_t i = 0; i < kPerformanceRepeatCount; i++) { absl::StrAppend(&input, recursive_message); } - string expected = "recursive_message { "; + std::string expected = "recursive_message { "; for (size_t i = 0; i < kPerformanceRepeatCount; i++) { absl::StrAppend(&expected, message_field, " "); } absl::StrAppend(&expected, "}"); - RunValidTextFormatTestProto2WithExpected( - absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField", - test_type_name, "Proto2"), - RECOMMENDED, input, expected); RunValidTextFormatTestWithExpected( absl::StrCat("TestTextFormatPerformanceMergeMessageWithRepeatedField", - test_type_name, "Proto3"), + test_type_name), RECOMMENDED, input, expected); } diff --git a/conformance/text_format_conformance_suite.h b/conformance/text_format_conformance_suite.h index 045fdc2a31..27de29e13a 100644 --- a/conformance/text_format_conformance_suite.h +++ b/conformance/text_format_conformance_suite.h @@ -8,7 +8,10 @@ #ifndef TEXT_FORMAT_CONFORMANCE_SUITE_H_ #define TEXT_FORMAT_CONFORMANCE_SUITE_H_ +#include + #include "conformance_test.h" +#include "google/protobuf/message.h" namespace google { namespace protobuf { @@ -19,41 +22,55 @@ class TextFormatConformanceTestSuite : public ConformanceTestSuite { private: void RunSuiteImpl() override; + + bool ParseTextFormatResponse(const conformance::ConformanceResponse& response, + const ConformanceRequestSetting& setting, + Message* test_message); + bool ParseResponse(const conformance::ConformanceResponse& response, + const ConformanceRequestSetting& setting, + Message* test_message) override; + + template + friend class TextFormatConformanceTestSuiteImpl; +}; + +template +class TextFormatConformanceTestSuiteImpl { + public: + explicit TextFormatConformanceTestSuiteImpl( + TextFormatConformanceTestSuite* suite); + + private: + using ConformanceRequestSetting = + TextFormatConformanceTestSuite::ConformanceRequestSetting; + using ConformanceLevel = TextFormatConformanceTestSuite::ConformanceLevel; + constexpr static ConformanceLevel RECOMMENDED = ConformanceLevel::RECOMMENDED; + constexpr static ConformanceLevel REQUIRED = ConformanceLevel::REQUIRED; + + void RunAllTests(); + + void RunGroupTests(); + void RunAnyTests(); + void RunTextFormatPerformanceTests(); void RunValidTextFormatTest(const std::string& test_name, ConformanceLevel level, const std::string& input); - void RunValidTextFormatTestProto2(const std::string& test_name, - ConformanceLevel level, - const std::string& input); void RunValidTextFormatTestWithExpected(const std::string& test_name, ConformanceLevel level, - const std::string& input, - const std::string& expected); - void RunValidTextFormatTestProto2WithExpected(const std::string& test_name, - ConformanceLevel level, - const std::string& input, - const std::string& expected); - void RunValidTextFormatTestWithMessage(const std::string& test_name, - ConformanceLevel level, - const std::string& input_text, - const Message& prototype); + const std::string& input_text, + const std::string& expected_text); + void RunValidUnknownTextFormatTest(const std::string& test_name, + const Message& message); void RunValidTextFormatTestWithMessage(const std::string& test_name, ConformanceLevel level, const std::string& input_text, - const std::string& expected_text, - const Message& prototype); - void RunValidUnknownTextFormatTest(const std::string& test_name, - const Message& message); + const Message& message); void ExpectParseFailure(const std::string& test_name, ConformanceLevel level, const std::string& input); - bool ParseTextFormatResponse(const conformance::ConformanceResponse& response, - const ConformanceRequestSetting& setting, - Message* test_message); - bool ParseResponse(const conformance::ConformanceResponse& response, - const ConformanceRequestSetting& setting, - Message* test_message) override; void TestTextFormatPerformanceMergeMessageWithRepeatedField( const std::string& test_type_name, const std::string& message_field); + + TextFormatConformanceTestSuite& suite_; }; } // namespace protobuf diff --git a/conformance/text_format_failure_list_cpp.txt b/conformance/text_format_failure_list_cpp.txt index a25f04faf2..fd2d7ada1f 100644 --- a/conformance/text_format_failure_list_cpp.txt +++ b/conformance/text_format_failure_list_cpp.txt @@ -1,20 +1,40 @@ Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex +Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal +Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes +Required.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString +Required.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString diff --git a/conformance/text_format_failure_list_python.txt b/conformance/text_format_failure_list_python.txt index 6bf7c1aa63..2f7f22471c 100644 --- a/conformance/text_format_failure_list_python.txt +++ b/conformance/text_format_failure_list_python.txt @@ -3,31 +3,6 @@ # TODO: These should be fixed. Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput - -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString -Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes -Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString -Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes -Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput diff --git a/conformance/text_format_failure_list_python_cpp.txt b/conformance/text_format_failure_list_python_cpp.txt index 91fc2ea3cd..b9da32dab8 100644 --- a/conformance/text_format_failure_list_python_cpp.txt +++ b/conformance/text_format_failure_list_python_cpp.txt @@ -1,27 +1,3 @@ -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput -Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes -Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString -Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes -Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString -Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes -Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput diff --git a/docs/design/editions/README.md b/docs/design/editions/README.md index 9443fb033b..c551f91ab0 100644 --- a/docs/design/editions/README.md +++ b/docs/design/editions/README.md @@ -24,6 +24,7 @@ The following topics are in this repository: * [Protobuf Editions Design: Features](protobuf-editions-design-features.md) * [Editions: Life of a Featureset](editions-life-of-a-featureset.md) * [Edition Zero Features](edition-zero-features.md) +* [Minimum Required Edition](minimum-required-edition.md) * [Protobuf Editions for Schema Producers](protobuf-editions-for-schema-producers.md) * [Stricter Schemas with Editions](stricter-schemas-with-editions.md) * [Edition Zero: JSON Handling](edition-zero-json-handling.md) @@ -34,3 +35,5 @@ The following topics are in this repository: * [Edition Evolution](edition-evolution.md) * [Edition Naming](edition-naming.md) * [Editions Feature Visibility](editions-feature-visibility.md) +* [Legacy Syntax Editions](legacy-syntax-editions.md) +* [Editions: Feature Extension Layout](editions-feature-extension-layout.md) \ No newline at end of file diff --git a/docs/design/editions/editions-feature-extension-layout.md b/docs/design/editions/editions-feature-extension-layout.md new file mode 100644 index 0000000000..67626a4388 --- /dev/null +++ b/docs/design/editions/editions-feature-extension-layout.md @@ -0,0 +1,150 @@ +# Editions: Feature Extension Layout + +**Author:** [@mkruskal-google](https://github.com/mkruskal-google), +[@zhangskz](https://github.com/zhangskz) + +**Approved:** 2023-08-23 + +## Background + +"[What are Protobuf Editions](what-are-protobuf-editions.md)" lays out a plan +for allowing for more targeted features not owned by the protobuf team. It uses +extensions of the global features proto to implement this. One thing that was +left a bit ambiguous was *who* should own these extensions. Language, code +generator, and runtime implementations are all similar but not identical +distinctions. + +"Editions Zero Feature: utf8_validation" (not available externally, though a +later version, +"[Editions Zero: utf8_validation Without Problematic Options](editions-zero-utf8_validation.md)" +is) is a recent plan to add a new set of generator features for utf8 validation. +While the sole feature we had originally created (`legacy_closed_enum` in Java +and C++) didn't have any ambiguity here, this one did. Specifically in Python, +the current behaviors across proto2/proto3 are distinct for all 3 +implementations: pure python, Python/C++, Python/upb. + +## Overview + +In meetings, we've discussed various alternatives, captured below. The original +plan was to make feature extensions runtime implementation-specific (e.g. C++, +Java, Python, upb). There are some notable complications that came up though: + +1. **Polyglot** - it's not clear how upb or C++ runtimes should behave in + multi-language situations. Which feature sets do they consider for runtime + behaviors? *Note: this is already a serious issue today, where all proto2 + strings and many proto3 strings are completely unsafe across languages.* + +2. **Shared Implementations** - Runtimes like upb and C++ are used as backing + implementations of multiple other languages (e.g. Python, Rust, Ruby, PHP). + If we have a single set of `upb` or `cpp` features, migrating to those + shared implementations would be more difficult (since there's no independent + switches per-language). *Note: this is already the situation we're in today, + where switching the runtime implementation can cause subtle and dangerous + behavior changes.* + +Given that we only have two behaviors, and one of them is unambiguous, it seems +reasonable to punt on this decision until we have more information. We may +encounter more edge cases that require feature extensions (and give us more +information) during the rollout of edition zero. We also have a lot of freedom +to re-model features in later editions, so keeping the initial implementation as +simple as possible seems best (i.e. Alternative 2). + +## Alternatives + +### Alternative 1: Runtime Implementation Features + +Features would be per-runtime implementation as originally described in +"Editions Zero Feature: utf8_validation." For example, Protobuf Python users +would set different features depending on the backing implementation (e.g. +`features.(pb.cpp).`, `features.(pb.upb).`). + +#### Pros + +* Most consistent with range of behaviors expressible pre-Editions + +#### Cons + +* Implementation may / should not be obvious to users. +* Lack of levers specifically for language / implementation combos. For + example, there is no way to set Python-C++ behavior independently of C++ + behavior which may make migration harder from other Python implementations. + +### Alternative 2: Generator Features + +Features would be per-generator only (i.e. each protoc plugin would own one set +of features). This was the second decision we made in later discussions, and +while very similar to the above alternative, it's more inline with our goal of +making features primarily for codegen. + +For example, all Python implementations would share the same set of features +(e.g. `features.(pb.python).`). However, certain features could be +targeted to specific implementations (e.g. +`features.(pb.python).upb_utf8_validation` would only be used by Python/upb). + +#### Pros + +* Allows independent controls of shared implementations in different target + languages (e.g. Python's upb feature won't affect PHP). + +#### Cons + +* Possible complexity in upb to understand which language's features to + respect. UPB is not currently aware of what language it is being used for. +* Limits in-process sharing across languages with shared implementations (e.g. + Python upb, PHP upb) in the case of conflicting behaviors. + * Additional checks may be needed. + +### Alternative 3: Migrate to bytes + +Since this whole discussion revolves around the utf8 validation feature, one +option would be to just remove it from edition zero. Instead of adding a new +toggle for UTF8 behavior, we could simply migrate everyone who doesn't enforce +utf8 today to `bytes`. This would likely need another new *codegen* feature for +generating byte getters/setters as strings, but that wouldn't have any of the +ambiguity we're seeing today. + +Unfortunately, this doesn't seem feasible because of all the different behaviors +laid out in "Editions Zero Feature: utf8_validation." UTF8 validation isn't +really a binary on/off decision, and it can vary widely between languages. There +are many cases where UTF8 is validated in **some** languages but not others, and +there's also the C++ "hint" behavior that logs errors but allows invalid UTF8. + +**Note:** This could still be partially done in a follow-up LSC by targeting +specific combinations of the new feature that disable validation in all relevant +languages. + +#### Pros + +* Punts on the issue, we wouldn't need any upb features and C++ features would + all be code-gen only +* Simplifies the situation, avoids adding a very complicated feature in + edition zero + +#### Cons + +* Not really possible given the current complexity +* There are O(10M) proto2 string fields that would be blindly changed to bytes + +### Alternative 4: Nested Features + +Another option is to allow for shared feature set messages. For example, upb +would define a feature message, but *not* make it an extension of the global +`FeatureSet`. Instead, languages with upb implementations would have a field of +this type to allow for finer-grained controls. C++ would both extend the global +`FeatureSet` and also be allowed as a field in other languages. + +For example, python utf8 validation could be specified as: + +We could have checks during feature validation that enforce that impossible +combinations aren't specified. For example, with our current implementation +`features.(pb.python).cpp` should always be identical to `features.(pb.cpp)`, +since we don't have any mechanism for distinguishing them. + +#### Pros + +* Much more explicit than options 1 and 2 + +#### Cons + +* Maybe too explicit? Proto owners would be forced to duplicate a lot of + features diff --git a/docs/design/editions/legacy-syntax-editions.md b/docs/design/editions/legacy-syntax-editions.md new file mode 100644 index 0000000000..4afcb4569e --- /dev/null +++ b/docs/design/editions/legacy-syntax-editions.md @@ -0,0 +1,144 @@ +# Legacy Syntax Editions + +**Author:** [@mkruskal-google](https://github.com/mkruskal-google) + +**Approved:** 2023-09-08 + +Should proto2/proto3 be treated as editions? + +## Background + +[Edition Zero Features](edition-zero-features.md) lays out our plan for edition +2023, which will unify proto2 and proto3. Since early in the design process, +we've discussed the possibility of making proto2 and proto3 "special" editions, +but never laid out what exactly it would look like or determined if it was +necessary. + +We recently redesigned editions to be represented as enums +([Edition Naming](edition-naming.md)), and also how edition defaults are +propagated to generators and runtimes +([Editions: Life of a FeatureSet](editions-life-of-a-featureset.md)). With these +changes, there could be an opportunity to special-case proto2 and proto3 in a +beneficial way. + +## Problem Description + +While the original plan was to keep editions and syntax orthogonal, that naively +means we'd be supporting two very different codebases. This has some serious +maintenance costs though, especially when it comes to test coverage. We could +expect to have sub-optimal test coverage of editions initially, which would +gradually become poor coverage of syntax later. Since we need to support both +syntax and editions long-term, this isn't ideal. + +In the implementation of editions in C++, we decided to unify a lot of the +infrastructure to avoid this issue. We define global feature sets for proto2 and +proto3, and try to use those internally instead of checking syntax directly. By +pushing the syntax/editions branch earlier in the stack, it gives us a lot of +indirect test coverage for editions much earlier. + +A separate issue is how Prototiller will support the conversion of syntax to +edition 2023. For features it knows about, we can hardcode defaults into the +transforms. However, third party feature owners will have no way of signaling +what the old proto2/proto3 behavior was, so Prototiller won't be able to provide +any transformations by default. They'd need to provide custom Prototiller +transforms hardcoding all of their features. + +## Recommended Solution + +We recommend adding two new special editions to our current set: + +``` +enum Edition { + EDITION_UNKNOWN = 0; + EDITION_PROTO2 = 998; + EDITION_PROTO3 = 999; + EDITION_2023 = 1000; +} +``` + +These will be treated the same as any other edition, except in our parser which +will reject `edition = "proto2"` and `edition = "proto3"` in proto files. The +real benefit here is that this allows features to specify what their +proto2/proto3 defaults are, making it easier for Prototiller to handle +migration. It also allows generators and runtimes to unify their internals more +completely, treating proto2/proto3 files exactly the same as editions. + +### Serialized Descriptors + +As we now know, there are a lot of serialized `descriptor.proto` descriptor sets +out there that need to continue working for O(months). In order to avoid +blocking edition zero for that long, we may need fallbacks in protoc for the +case where feature resolution *fails*. If the file is proto2/proto3, failure +should result in a fallback to the existing hardcoded defaults. We can remove +these later once we're willing to break stale `descriptor.proto` snapshots that +predate the changes in this doc. + +### Bootstrapping + +In order to get feature resolution running in proto2 and proto3, we need to be +able to support bootstrapped protos. For these builds, we can't use any +reflection without deadlocking, which means feature defaults can't be compiled +during runtime. We would have had to solve this problem anyway when it came time +to migrate these protos to editions, but this proposal forces our hand early. +Luckily, "Editions: Life of a FeatureSet" already set us up for this scenario, +and we have Blaze rules for embedding these defaults into code. For C++ +specifically, this will need to be checked in alongside the other bootstrapped +protos. Other languages will be able to do this more dynamically via genrules. + +### Feature Inference + +While we can calculate defaults using the same logic as in editions, actually +inferring "features" from proto2/proto3 needs some custom code. For example: + +* The `required` keyword sets `LEGACY_REQUIRED` feature +* The `optional` keyword in proto3 sets `EXPLICIT` presence +* The `group` keyword implies `DELIMITED` encoding +* The `enforce_utf8` options flips between `PACKED` and `EXPANDED` encoding + +This logic needs to be written in code, and will need to be duplicated in every +language we support. Any language-specific feature transformations will also +need to be included in that language. To make this as portable as possible, we +will define functions like: + +Each type of descriptor will have its own set of transformations that should be +applied to its features for legacy editions. + +#### Pros + +* Makes it clearer that proto2/proto3 are "like" editions + +* Gives Prototiller a little more information in the transformation from + proto2/proto3 to editions (not necessarily 2023) + +* Allows proto2/proto3 defaults to be specified in a single location + +* Makes unification of syntax/edition code easier to implement in runtimes + +* Allows cross-language proto2/proto3 testing with the conformance framework + mentioned in "Editions: Life of a FeatureSet" + +#### Cons + +* Adds special-case legacy editions, which may be somewhat confusing + +* We will need to port feature inference logic across all languages. This is + arguably cheaper than maintaining branched proto2/proto3 code in all + languages though + +## Considered Alternatives + +### Do Nothing + +If we do nothing, there will be no built-in unification of syntax and editions. +Runtimes could choose any point to split the logic. + +#### Pros + +* Requires no changes to editions code + +#### Cons + +* Likely results in lower test coverage +* May hide issues until we start rolling out edition 2023 +* Prototiller would have to hard-code proto2/proto3 defaults of features it + knows, and couldn't even try to migrate runtimes it doesn't diff --git a/docs/design/editions/minimum-required-edition.md b/docs/design/editions/minimum-required-edition.md new file mode 100644 index 0000000000..fd61ea1966 --- /dev/null +++ b/docs/design/editions/minimum-required-edition.md @@ -0,0 +1,139 @@ +# Minimum Required Edition + +**Author:** [@mcy](https://github.com/mcy) + +**Approved:** 2022-11-15 + +A versioning mechanism for descriptors that ensures old runtimes do not load +descriptors that are "too new." + +## Background + +Suppose we decide to add a novel definition like + +``` +const int32 MY_CONSTANT = 42; +``` + +to the Protobuf language. This would entail a descriptor change to track the +values of constants, but they would not be loaded properly by older runtimes. +This document describes an addition to `descriptor.proto` that prevents this +version mismatch issue. + +[Protobuf Editions](what-are-protobuf-editions.md) intends to add the concept of +an edition to Protobuf, which will be an approximately-annually incrementing +value. Because of their annual nature, and because runtimes need to be updated +to handle new features they implement regardless, we can use them as a poison +pill for old runtimes that try to load descriptors that are "too new." + +## Overview + +We propose adding a new field to `FileDescriptorProto`: + +``` +optional string minimum_required_edition = ...; +``` + +This field would exist alongside the `edition` field, and would have the +following semantics: + +Every Protobuf runtime implementation must specify the newest edition whose +constructs it can handle (at a particular rev of that implementation). If that +edition is less than `minimum_required_edition`, loading the descriptor must +fail. + +"Less than" is defined per the edition total order given in +[Life of an Edition](life-of-an-edition.md). To restate it, it is the following +algorithm: + +``` +def edition_less_than(a, b): + parts_a = a.split(".") + parts_b = b.split(".") + for i in range(0, min(len(parts_a), len(parts_b))): + if int(parts_a[i]) < int(parts_b[i]): return True + return len(a) < len(b) +``` + +`protoc` should keep track of which constructions require which minimum edition. +For example, if constants are introduced in edition 2025, but they are not +present in a file, `protoc` should not require that runtimes understand +constants by picking a lower edition, like 2023 (assuming no other construct +requires a higher edition). + +In particular, the following changes should keep the minimum edition constant, +with all other things unchanged: + +* An upgrade of the proto compiler. +* Upgrading the specified edition of a file via Prototiller. + +### Bootstrapping Concerns + +"Epochs for `descriptor.proto`" (not available externally) describes a potential +issue with bootstrapping. It is not the case here: minimum edition is only +incremented once a particular file uses a new feature. Since `descriptor.proto` +and other schemas used by `protoc` and the backends would not use new features +immediately, introducing a new feature does not immediately stop the compiler +from being able to compile itself. + +### Concerns for Schema Producers + +Schema producers should consider changes to their schemas that increase the +minimum required edition to be breaking changes, since it will stop compiled +descriptors from being loaded at runtime. + +## Recommendation + +We recommend adding the aforementioned minimum required edition field, along +with the semantics it entails. This logic should be implemented entirely in the +protoc frontend. + +## Alternatives + +### Use a Non-Editions Version Number + +Rather than using the editions value, use some other version number. This number +would be incremented rarely (3-5 year horizon). This is the approach proposed +in "Epochs for `descriptor.proto`." + +#### Pros + +* Does not re-use the editions value for a semantically-different meaning; the + edition remains being "just" a key into a table of features defaults. + +#### Cons + +* Introduces another version number to Protobuf that increments at its own + cadence. +* Could potentially be confused with the edition value, even though they serve + distinct purposes. + +### Minimum Required Edition Should Not Be Minimal + +The proto compiler should not guarantee that the minimum required edition is as +small as it could possibly be. + +#### Pros + +* Reduces implementation burden. + +#### Cons + +* This introduces situations where an upgrade of the proto compiler, or an + innocuous change to a schema, can lead the the minimum required edition + being incremented. This is a problem for schema producers. + +### Do Nothing + +#### Pros + +* Reduces churn in runtimes, since they do not need to implement new handling + for new *editions* (as contrasted to just *features)* regularly. +* Avoids a situation where old software cannot load new descriptors at + runtime. + +#### Cons + +* Commits us to never changing the descriptor wire format in + backwards-incompatible ways, which has far-reaching effects on evolution. + These consequences are discussed in "Epochs for `descriptor.proto`." diff --git a/docs/options.md b/docs/options.md index 18b6b410fa..aee889ecdf 100644 --- a/docs/options.md +++ b/docs/options.md @@ -486,3 +486,8 @@ with info about your project (name and website) so we can add an entry for you. * Website: https://square.github.io/wire/ * Extensions: 1185 + +1. Protons + + * Website: https://github.com/ipfs/protons + * Extensions: 1186 diff --git a/docs/third_party.md b/docs/third_party.md index ed63375bf6..a3763a974e 100644 --- a/docs/third_party.md +++ b/docs/third_party.md @@ -31,6 +31,8 @@ These are projects we know about implementing Protocol Buffers for other program * Clojure: http://github.com/ninjudd/clojure-protobuf * Clojure: https://github.com/clojusc/protobuf * Clojure: https://protojure.readthedocs.io +* Clojure: https://github.com/s-expresso/clojobuf +* ClojureScript: https://github.com/s-expresso/clojobuf * Common Lisp: http://github.com/brown/protobuf * Common Lisp: http://github.com/qitab/cl-protobuf * D: https://github.com/dcarp/protobuf-d @@ -233,3 +235,8 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d * [protobuf-decoder-explainer - Web page which decodes and explains pasted binary Protocol Buffers](https://github.com/jamesdbrock/protobuf-decoder-explainer) +* [rubberbuf - dynamically transpile protobuf into AST](https://github.com/s-expresso/rubberbuf) + `clojure` `clojurescript` +* [clojobuf-serdes - low level serialize/deserialize library for protobuf + binary format](https://github.com/s-expresso/clojobuf-codec) `clojure` + `clojurescript` 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 dbe3072fb7..86f2bb43b8 100644 --- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -9,6 +9,7 @@ package com.google.protobuf; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertThrows; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; @@ -213,28 +214,28 @@ public class GeneratedMessageTest { @Test public void testGetExtensionFieldOutOfBound() { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); - try { - builder.getRepeatedField(UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0); - assertWithMessage("Expected IndexOutOfBoundsException to be thrown").fail(); - } catch (IndexOutOfBoundsException expected) { - } - try { - builder.getExtension(UnittestProto.repeatedNestedMessageExtension, 0); - assertWithMessage("Expected IndexOutOfBoundsException to be thrown").fail(); - } catch (IndexOutOfBoundsException expected) { - } + + assertThrows( + "Expected IndexOutOfBoundsException to be thrown", + IndexOutOfBoundsException.class, + () -> + builder.getRepeatedField( + UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0)); + assertThrows( + "Expected IndexOutOfBoundsException to be thrown", + IndexOutOfBoundsException.class, + () -> builder.getExtension(UnittestProto.repeatedNestedMessageExtension, 0)); TestAllExtensions extensionsMessage = builder.build(); - try { - extensionsMessage.getRepeatedField( - UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0); - assertWithMessage("Expected IndexOutOfBoundsException to be thrown").fail(); - } catch (IndexOutOfBoundsException expected) { - } - try { - extensionsMessage.getExtension(UnittestProto.repeatedNestedMessageExtension, 0); - assertWithMessage("Expected IndexOutOfBoundsException to be thrown").fail(); - } catch (IndexOutOfBoundsException expected) { - } + assertThrows( + "Expected IndexOutOfBoundsException to be thrown", + IndexOutOfBoundsException.class, + () -> + extensionsMessage.getRepeatedField( + UnittestProto.repeatedNestedMessageExtension.getDescriptor(), 0)); + assertThrows( + "Expected IndexOutOfBoundsException to be thrown", + IndexOutOfBoundsException.class, + () -> extensionsMessage.getExtension(UnittestProto.repeatedNestedMessageExtension, 0)); } @Test @@ -365,78 +366,51 @@ public class GeneratedMessageTest { if (list == Collections.emptyList()) { // OKAY -- Need to check this b/c EmptyList allows you to call clear. } else { - try { - list.clear(); - assertWithMessage("List wasn't immutable").fail(); - } catch (UnsupportedOperationException e) { - // good - } + assertThrows( + "List wasn't immutable", UnsupportedOperationException.class, () -> list.clear()); } } @Test public void testSettersRejectNull() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - try { - builder.setOptionalString(null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.setOptionalBytes(null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.setOptionalNestedMessage((TestAllTypes.NestedMessage) null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.setOptionalNestedMessage((TestAllTypes.NestedMessage.Builder) null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.setOptionalNestedEnum(null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.addRepeatedString(null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.addRepeatedBytes(null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage) null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage.Builder) null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.addRepeatedNestedEnum(null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } + + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setOptionalString(null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setOptionalNestedMessage((TestAllTypes.NestedMessage) null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setOptionalNestedMessage((TestAllTypes.NestedMessage.Builder) null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setOptionalNestedEnum(null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.addRepeatedString(null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.addRepeatedBytes(null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage) null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage.Builder) null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.addRepeatedNestedEnum(null)); } @Test @@ -454,45 +428,35 @@ public class GeneratedMessageTest { builder.addRepeatedString("one"); builder.addRepeatedString("two"); - try { - builder.setRepeatedString(1, null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setRepeatedString(1, null)); builder.addRepeatedBytes(TestUtil.toBytes("one")); builder.addRepeatedBytes(TestUtil.toBytes("two")); - try { - builder.setRepeatedBytes(1, null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setRepeatedBytes(1, null)); builder.addRepeatedNestedMessage(TestAllTypes.NestedMessage.newBuilder().setBb(218).build()); builder.addRepeatedNestedMessage(TestAllTypes.NestedMessage.newBuilder().setBb(456).build()); - try { - builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - try { - builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage.Builder) null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null)); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage.Builder) null)); builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.FOO); builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR); - try { - builder.setRepeatedNestedEnum(1, null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.setRepeatedNestedEnum(1, null)); } @Test @@ -518,33 +482,24 @@ public class GeneratedMessageTest { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); ForeignMessage foreignMessage = ForeignMessage.newBuilder().setC(12).build(); - try { - builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage, (ForeignMessage) null)); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - - try { - builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ, null)); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - - try { - builder.addAllRepeatedString(Arrays.asList("one", null)); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } - - try { - builder.addAllRepeatedBytes(Arrays.asList(TestUtil.toBytes("one"), null)); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> + builder.addAllRepeatedForeignMessage( + Arrays.asList(foreignMessage, (ForeignMessage) null))); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ, null))); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.addAllRepeatedString(Arrays.asList("one", null))); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.addAllRepeatedBytes(Arrays.asList(TestUtil.toBytes("one"), null))); } @Test @@ -570,23 +525,19 @@ public class GeneratedMessageTest { assertThat(builder.getRepeatedString(1)).isEqualTo("two"); assertThat(builder.getRepeatedString(2)).isEqualTo("three"); - try { - builder.addAllRepeatedString(stringIterable); - assertWithMessage("Exception was not thrown").fail(); - } catch (IllegalStateException e) { - // We expect this exception. - } + assertThrows( + "Exception was not thrown", + IllegalStateException.class, + () -> builder.addAllRepeatedString(stringIterable)); } @Test public void testMergeFromOtherRejectsNull() throws Exception { - try { - TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - builder.mergeFrom((TestAllTypes) null); - assertWithMessage("Exception was not thrown").fail(); - } catch (NullPointerException e) { - // We expect this exception. - } + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + assertThrows( + "Exception was not thrown", + NullPointerException.class, + () -> builder.mergeFrom((TestAllTypes) null)); } @Test @@ -781,13 +732,11 @@ public class GeneratedMessageTest { @Test public void testGetBuilderForNonMessageExtensionField() { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); - try { - // This should throw an exception because the extension field is not a message. - builder.newBuilderForField(UnittestProto.optionalInt32Extension.getDescriptor()); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // This exception is expected. - } + // This should throw an exception because the extension field is not a message. + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> builder.newBuilderForField(UnittestProto.optionalInt32Extension.getDescriptor())); } @Test @@ -1388,36 +1337,26 @@ public class GeneratedMessageTest { public void testGetFieldBuilderNotSupportedException() { Descriptor descriptor = TestAllTypes.getDescriptor(); TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - try { - builder.getFieldBuilder(descriptor.findFieldByName("optional_int32")); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } - try { - builder.getFieldBuilder(descriptor.findFieldByName("optional_nested_enum")); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } - try { - builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32")); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } - try { - builder.getFieldBuilder(descriptor.findFieldByName("repeated_nested_enum")); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } - try { - builder.getFieldBuilder(descriptor.findFieldByName("repeated_nested_message")); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> builder.getFieldBuilder(descriptor.findFieldByName("optional_int32"))); + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> builder.getFieldBuilder(descriptor.findFieldByName("optional_nested_enum"))); + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32"))); + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> builder.getFieldBuilder(descriptor.findFieldByName("repeated_nested_enum"))); + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> builder.getFieldBuilder(descriptor.findFieldByName("repeated_nested_message"))); } // Test that when the default outer class name conflicts with another type @@ -1873,42 +1812,38 @@ public class GeneratedMessageTest { public void testGetRepeatedFieldBuilderNotSupportedException() { Descriptor descriptor = TestAllTypes.getDescriptor(); TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - try { - builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_int32"), 0); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } - try { - builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_nested_enum"), 0); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } - try { - builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_int32"), 0); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } - try { - builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_nested_enum"), 0); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } - try { - builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_nested_message"), 0); - assertWithMessage("Exception was not thrown").fail(); - } catch (UnsupportedOperationException e) { - // We expect this exception. - } + + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_int32"), 0)); + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> + builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_nested_enum"), 0)); + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_int32"), 0)); + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> + builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_nested_enum"), 0)); + assertThrows( + "Exception was not thrown", + UnsupportedOperationException.class, + () -> + builder.getRepeatedFieldBuilder( + descriptor.findFieldByName("optional_nested_message"), 0)); } private static final FieldDescriptor OPTIONAL_NESTED_MESSAGE_EXTENSION = UnittestProto.getDescriptor().findExtensionByName("optional_nested_message_extension"); private static final FieldDescriptor REPEATED_NESTED_MESSAGE_EXTENSION = UnittestProto.getDescriptor().findExtensionByName("repeated_nested_message_extension"); + // A compile-time check that TestAllExtensions.Builder does in fact extend // GeneratedMessageV3.ExtendableBuilder. The tests below assume that it does. static { diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c index 0c4bbfb484..f999768b48 100644 --- a/php/ext/google/protobuf/php-upb.c +++ b/php/ext/google/protobuf/php-upb.c @@ -5803,8 +5803,10 @@ bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) { } } -void upb_Arena_IncRefFor(upb_Arena* arena, const void* owner) { +bool upb_Arena_IncRefFor(upb_Arena* arena, const void* owner) { _upb_ArenaRoot r; + if (upb_Arena_HasInitialBlock(arena)) return false; + retry: r = _upb_Arena_FindRoot(arena); if (upb_Atomic_CompareExchangeWeak( @@ -5813,7 +5815,7 @@ retry: _upb_Arena_RefCountFromTagged(r.tagged_count) + 1), memory_order_release, memory_order_acquire)) { // We incremented it successfully, so we are done. - return; + return true; } // We failed update due to parent switching on the arena. goto retry; diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h index ec91368750..b0621443ed 100644 --- a/php/ext/google/protobuf/php-upb.h +++ b/php/ext/google/protobuf/php-upb.h @@ -561,7 +561,7 @@ UPB_API upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc); UPB_API void upb_Arena_Free(upb_Arena* a); UPB_API bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b); -void upb_Arena_IncRefFor(upb_Arena* arena, const void* owner); +bool upb_Arena_IncRefFor(upb_Arena* arena, const void* owner); void upb_Arena_DecRefFor(upb_Arena* arena, const void* owner); void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size); diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php index 578e606ec7..a427e4889f 100644 --- a/php/src/Google/Protobuf/Internal/Message.php +++ b/php/src/Google/Protobuf/Internal/Message.php @@ -2014,4 +2014,56 @@ class Message } return $size; } + + public function __debugInfo() + { + if (is_a($this, 'Google\Protobuf\FieldMask')) { + return ['paths' => $this->getPaths()->__debugInfo()]; + } + + if (is_a($this, 'Google\Protobuf\Value')) { + switch ($this->getKind()) { + case 'null_value': + return ['nullValue' => $this->getNullValue()]; + case 'number_value': + return ['numberValue' => $this->getNumberValue()]; + case 'string_value': + return ['stringValue' => $this->getStringValue()]; + case 'bool_value': + return ['boolValue' => $this->getBoolValue()]; + case 'struct_value': + return ['structValue' => $this->getStructValue()->__debugInfo()]; + case 'list_value': + return ['listValue' => $this->getListValue()->__debugInfo()]; + } + return []; + } + + if (is_a($this, 'Google\Protobuf\BoolValue') + || is_a($this, 'Google\Protobuf\BytesValue') + || is_a($this, 'Google\Protobuf\DoubleValue') + || is_a($this, 'Google\Protobuf\FloatValue') + || is_a($this, 'Google\Protobuf\StringValue') + || is_a($this, 'Google\Protobuf\Int32Value') + || is_a($this, 'Google\Protobuf\Int64Value') + || is_a($this, 'Google\Protobuf\UInt32Value') + || is_a($this, 'Google\Protobuf\UInt64Value') + ) { + return [ + 'value' => json_decode($this->serializeToJsonString(), true), + ]; + } + + if ( + is_a($this, 'Google\Protobuf\Duration') + || is_a($this, 'Google\Protobuf\Timestamp') + ) { + return [ + 'seconds' => $this->getSeconds(), + 'nanos' => $this->getNanos(), + ]; + } + + return json_decode($this->serializeToJsonString(), true); + } } diff --git a/php/src/Google/Protobuf/Internal/RepeatedField.php b/php/src/Google/Protobuf/Internal/RepeatedField.php index 8f56863fe9..3d9e66d488 100644 --- a/php/src/Google/Protobuf/Internal/RepeatedField.php +++ b/php/src/Google/Protobuf/Internal/RepeatedField.php @@ -238,4 +238,17 @@ class RepeatedField implements \ArrayAccess, \IteratorAggregate, \Countable { return count($this->container); } + + public function __debugInfo() + { + return array_map( + function ($item) { + if ($item instanceof Message || $item instanceof RepeatedField) { + return $item->__debugInfo(); + } + return $item; + }, + iterator_to_array($this) + ); + } } diff --git a/php/tests/DebugInfoTest.php b/php/tests/DebugInfoTest.php new file mode 100644 index 0000000000..296f0ef1e5 --- /dev/null +++ b/php/tests/DebugInfoTest.php @@ -0,0 +1,597 @@ +markTestSkipped('__debugInfo is not supported for the protobuf extension'); + } + } + + public function testVarDumpOutput() + { + $m = new DoubleValue(); + $m->setValue(1.5); + var_dump($m); + $regex = << + float(1.5) +} +EOL; + $this->expectOutputRegex('/' . sprintf(preg_quote($regex), '\d+') . '/'); + } + + public function testTopLevelDoubleValue() + { + $m = new DoubleValue(); + $m->setValue(1.5); + $this->assertSame(['value' => 1.5], $m->__debugInfo()); + } + + public function testTopLevelFloatValue() + { + $m = new FloatValue(); + $m->setValue(1.5); + $this->assertSame(['value' => 1.5], $m->__debugInfo()); + } + + public function testTopLevelInt32Value() + { + $m = new Int32Value(); + $m->setValue(1); + $this->assertSame(['value' => 1], $m->__debugInfo()); + } + + public function testTopLevelUInt32Value() + { + $m = new UInt32Value(); + $m->setValue(1); + $this->assertSame(['value' => 1], $m->__debugInfo()); + } + + public function testTopLevelInt64Value() + { + $m = new Int64Value(); + $m->setValue(1); + $this->assertSame(['value' => '1'], $m->__debugInfo()); + } + + public function testTopLevelUInt64Value() + { + $m = new UInt64Value(); + $m->setValue(1); + $this->assertSame(['value' => '1'], $m->__debugInfo()); + } + + public function testTopLevelStringValue() + { + $m = new StringValue(); + $m->setValue("a"); + $this->assertSame(['value' => 'a'], $m->__debugInfo()); + } + + public function testTopLevelBoolValue() + { + $m = new BoolValue(); + $m->setValue(true); + $this->assertSame(['value' => true], $m->__debugInfo()); + } + + public function testTopLevelBytesValue() + { + $m = new BytesValue(); + $m->setValue("a"); + $this->assertSame(['value' => 'YQ=='], $m->__debugInfo()); + } + + public function testTopLevelLongBytesValue() + { + $m = new BytesValue(); + $data = $this->generateRandomString(12007); + $m->setValue($data); + $expected = base64_encode($data); + $this->assertSame(['value' => $expected], $m->__debugInfo()); + } + + public function testJsonEncodeNullSubMessage() + { + $from = new TestMessage(); + $from->setOptionalMessage(null); + $data = $from->__debugInfo(); + $this->assertEquals([], $data); + } + + public function testDuration() + { + $m = new Google\Protobuf\Duration(); + $m->setSeconds(1234); + $m->setNanos(999999999); + $this->assertEquals([ + 'seconds' => 1234, + 'nanos' => 999999999, + ], $m->__debugInfo()); + } + + public function testTimestamp() + { + $m = new Google\Protobuf\Timestamp(); + $m->setSeconds(946684800); + $m->setNanos(123456789); + $this->assertEquals([ + 'seconds' => 946684800, + 'nanos' => 123456789, + ], $m->__debugInfo()); + } + + public function testTopLevelValue() + { + $m = new Value(); + $m->setStringValue("a"); + $this->assertSame(['stringValue' => 'a'], $m->__debugInfo()); + + $m = new Value(); + $m->setNumberValue(1.5); + $this->assertSame(['numberValue' => 1.5], $m->__debugInfo()); + + $m = new Value(); + $m->setBoolValue(true); + $this->assertSame(['boolValue' => true], $m->__debugInfo()); + + $m = new Value(); + $m->setNullValue(\Google\Protobuf\NullValue::NULL_VALUE); + $this->assertSame(['nullValue' => 0], $m->__debugInfo()); + + $m = new Value(); + $struct = new Struct(); + $map = $struct->getFields(); + $sub = new Value(); + $sub->setNumberValue(1.5); + $map["a"] = $sub; + $m->setStructValue($struct); + $this->assertSame(['structValue' => ['a' => 1.5]], $m->__debugInfo()); + + $m = new Value(); + $list = new ListValue(); + $arr = $list->getValues(); + $sub = new Value(); + $sub->setNumberValue(1.5); + $arr[] = $sub; + $m->setListValue($list); + $this->assertSame(['listValue' => [1.5]], $m->__debugInfo()); + } + + public function testTopLevelListValue() + { + $m = new ListValue(); + $arr = $m->getValues(); + $sub = new Value(); + $sub->setNumberValue(1.5); + $arr[] = $sub; + $this->assertSame([1.5], $m->__debugInfo()); + } + + public function testEmptyListValue() + { + $m = new Struct(); + $m->setFields(['test' => (new Value())->setListValue(new ListValue())]); + $this->assertSame(['test' => []], $m->__debugInfo()); + } + + public function testTopLevelStruct() + { + $m = new Struct(); + $map = $m->getFields(); + $sub = new Value(); + $sub->setNumberValue(1.5); + $map["a"] = $sub; + $this->assertSame(['a' => 1.5], $m->__debugInfo()); + } + + public function testEmptyStruct() + { + $m = new Struct(); + $m->setFields(['test' => (new Value())->setStructValue(new Struct())]); + $this->assertSame(['test' => []], $m->__debugInfo()); + } + + public function testEmptyValue() + { + $m = new Value(); + $this->assertSame([], $m->__debugInfo()); + } + + public function testTopLevelAny() + { + // Test a normal message. + $packed = new TestMessage(); + $packed->setOptionalInt32(123); + $packed->setOptionalString("abc"); + + $m = new Any(); + $m->pack($packed); + $expected = [ + '@type' => 'type.googleapis.com/foo.TestMessage', + 'optionalInt32' => 123, + 'optionalString' => 'abc', + ]; + $result = $m->__debugInfo(); + $this->assertSame($expected, $result); + + // Test a well known message. + $packed = new Int32Value(); + $packed->setValue(123); + + $m = new Any(); + $m->pack($packed); + $this->assertSame([ + '@type' => 'type.googleapis.com/google.protobuf.Int32Value', + 'value' => 123 + ], $m->__debugInfo()); + + // Test an Any message. + $outer = new Any(); + $outer->pack($m); + $this->assertSame([ + '@type' => 'type.googleapis.com/google.protobuf.Any', + 'value' => [ + '@type' => 'type.googleapis.com/google.protobuf.Int32Value', + 'value' => 123 + ], + ], $outer->__debugInfo()); + + // Test a Timestamp message. + $packed = new Google\Protobuf\Timestamp(); + $packed->setSeconds(946684800); + $packed->setNanos(123456789); + $m = new Any(); + $m->pack($packed); + $this->assertSame([ + '@type' => 'type.googleapis.com/google.protobuf.Timestamp', + 'value' => '2000-01-01T00:00:00.123456789Z', + ], $m->__debugInfo()); + } + + public function testAnyWithDefaultWrapperMessagePacked() + { + $any = new Any(); + $any->pack(new TestInt32Value([ + 'field' => new Int32Value(['value' => 0]), + ])); + $this->assertSame( + ['@type' => 'type.googleapis.com/foo.TestInt32Value', 'field' => 0], + $any->__debugInfo() + ); + } + + public function testTopLevelFieldMask() + { + $m = new FieldMask(); + $m->setPaths(["foo.bar_baz", "qux"]); + $this->assertSame(['paths' => ['foo.bar_baz', 'qux']], $m->__debugInfo()); + } + + public function testEmptyAnySerialization() + { + $m = new EmptyAnySerialization(); + + $any = new Any(); + $any->pack($m); + + $data = $any->__debugInfo(); + $this->assertEquals(['@type' => 'type.googleapis.com/foo.EmptyAnySerialization'], $data); + } + + public function testRepeatedStringValue() + { + $m = new TestStringValue(); + $r = [new StringValue(['value' => 'a'])]; + $m->setRepeatedField($r); + $this->assertSame(['repeatedField' => ['a']], $m->__debugInfo()); + } + + public function testMapStringValue() + { + $m = new TestStringValue(); + $m->mergeFromJsonString("{\"map_field\":{\"1\": \"a\"}}"); + $this->assertSame(['mapField' => [1 => 'a']], $m->__debugInfo()); + } + + public function testNestedAny() + { + // Make sure packed message has been created at least once. + $m = new TestAny(); + $m->mergeFromJsonString( + "{\"any\":{\"optionalInt32\": 1, " . + "\"@type\":\"type.googleapis.com/foo.TestMessage\", " . + "\"optionalInt64\": 2}}"); + $this->assertSame([ + 'any' => [ + '@type' => 'type.googleapis.com/foo.TestMessage', + 'optionalInt32' => 1, + 'optionalInt64' => '2', + ] + ], $m->__debugInfo()); + } + + public function testEnum() + { + $m = new TestMessage(); + $m->setOneofEnum(TestEnum::ZERO); + $this->assertSame(['oneofEnum' => 'ZERO'], $m->__debugInfo()); + } + + public function testTopLevelRepeatedField() + { + $r1 = new RepeatedField(GPBType::class); + $r1[] = 'a'; + $this->assertSame(['a'], $r1->__debugInfo()); + + $r2 = new RepeatedField(TestMessage::class); + $r2[] = new TestMessage(['optional_int32' => -42]); + $r2[] = new TestMessage(['optional_int64' => 43]); + $this->assertSame([ + ['optionalInt32' => -42], + ['optionalInt64' => '43'], + ], $r2->__debugInfo()); + + $r3 = new RepeatedField(RepeatedField::class); + $r3[] = $r1; + $r3[] = $r2; + + $this->assertSame([ + ['a'], + [ + ['optionalInt32' => -42], + ['optionalInt64' => '43'], + ], + ], $r3->__debugInfo()); + } + + public function testEverything() + { + $m = new TestMessage([ + 'optional_int32' => -42, + 'optional_int64' => -43, + 'optional_uint32' => 42, + 'optional_uint64' => 43, + 'optional_sint32' => -44, + 'optional_sint64' => -45, + 'optional_fixed32' => 46, + 'optional_fixed64' => 47, + 'optional_sfixed32' => -46, + 'optional_sfixed64' => -47, + 'optional_float' => 1.5, + 'optional_double' => 1.6, + 'optional_bool' => true, + 'optional_string' => 'a', + 'optional_bytes' => 'bbbb', + 'optional_enum' => TestEnum::ONE, + 'optional_message' => new Sub([ + 'a' => 33 + ]), + 'repeated_int32' => [-42, -52], + 'repeated_int64' => [-43, -53], + 'repeated_uint32' => [42, 52], + 'repeated_uint64' => [43, 53], + 'repeated_sint32' => [-44, -54], + 'repeated_sint64' => [-45, -55], + 'repeated_fixed32' => [46, 56], + 'repeated_fixed64' => [47, 57], + 'repeated_sfixed32' => [-46, -56], + 'repeated_sfixed64' => [-47, -57], + 'repeated_float' => [1.5, 2.5], + 'repeated_double' => [1.6, 2.6], + 'repeated_bool' => [true, false], + 'repeated_string' => ['a', 'c'], + 'repeated_bytes' => ['bbbb', 'dddd'], + 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE], + 'repeated_message' => [new Sub(['a' => 34]), + new Sub(['a' => 35])], + 'map_int32_int32' => [-62 => -62], + 'map_int64_int64' => [-63 => -63], + 'map_uint32_uint32' => [62 => 62], + 'map_uint64_uint64' => [63 => 63], + 'map_sint32_sint32' => [-64 => -64], + 'map_sint64_sint64' => [-65 => -65], + 'map_fixed32_fixed32' => [66 => 66], + 'map_fixed64_fixed64' => [67 => 67], + 'map_sfixed32_sfixed32' => [-68 => -68], + 'map_sfixed64_sfixed64' => [-69 => -69], + 'map_int32_float' => [1 => 3.5], + 'map_int32_double' => [1 => 3.6], + 'map_bool_bool' => [true => true], + 'map_string_string' => ['e' => 'e'], + 'map_int32_bytes' => [1 => 'ffff'], + 'map_int32_enum' => [1 => TestEnum::ONE], + 'map_int32_message' => [1 => new Sub(['a' => 36])], + ]); + + $this->assertSame([ + 'optionalInt32' => -42, + 'optionalInt64' => '-43', + 'optionalUint32' => 42, + 'optionalUint64' => '43', + 'optionalSint32' => -44, + 'optionalSint64' => '-45', + 'optionalFixed32' => 46, + 'optionalFixed64' => '47', + 'optionalSfixed32' => -46, + 'optionalSfixed64' => '-47', + 'optionalFloat' => 1.5, + 'optionalDouble' => 1.6, + 'optionalBool' => true, + 'optionalString' => 'a', + 'optionalBytes' => 'YmJiYg==', + 'optionalEnum' => 'ONE', + 'optionalMessage' => [ + 'a' => 33, + ], + 'repeatedInt32' => [ + -42, + -52, + ], + 'repeatedInt64' => [ + '-43', + '-53', + ], + 'repeatedUint32' => [ + 42, + 52, + ], + 'repeatedUint64' => [ + '43', + '53', + ], + 'repeatedSint32' => [ + -44, + -54, + ], + 'repeatedSint64' => [ + '-45', + '-55', + ], + 'repeatedFixed32' => [ + 46, + 56, + ], + 'repeatedFixed64' => [ + '47', + '57', + ], + 'repeatedSfixed32' => [ + -46, + -56, + ], + 'repeatedSfixed64' => [ + '-47', + '-57', + ], + 'repeatedFloat' => [ + 1.5, + 2.5, + ], + 'repeatedDouble' => [ + 1.6, + 2.6, + ], + 'repeatedBool' => [ + true, + false, + ], + 'repeatedString' => [ + 'a', + 'c', + ], + 'repeatedBytes' => [ + 'YmJiYg==', + 'ZGRkZA==', + ], + 'repeatedEnum' => [ + 'ZERO', + 'ONE', + ], + 'repeatedMessage' => [ + [ + 'a' => 34, + ], + [ + 'a' => 35, + ], + ], + 'mapInt32Int32' => [ + -62 => -62, + ], + 'mapInt64Int64' => [ + -63 => '-63', + ], + 'mapUint32Uint32' => [ + 62 => 62, + ], + 'mapUint64Uint64' => [ + 63 => '63', + ], + 'mapSint32Sint32' => [ + -64 => -64, + ], + 'mapSint64Sint64' => [ + -65 => '-65', + ], + 'mapFixed32Fixed32' => [ + 66 => 66, + ], + 'mapFixed64Fixed64' => [ + 67 => '67', + ], + 'mapSfixed32Sfixed32' => [ + -68 => -68, + ], + 'mapSfixed64Sfixed64' => [ + -69 => '-69', + ], + 'mapInt32Float' => [ + 1 => 3.5, + ], + 'mapInt32Double' => [ + 1 => 3.6, + ], + 'mapBoolBool' => [ + 'true' => true, + ], + 'mapStringString' => [ + 'e' => 'e', + ], + 'mapInt32Bytes' => [ + 1 => 'ZmZmZg==', + ], + 'mapInt32Enum' => [ + 1 => 'ONE', + ], + 'mapInt32Message' => [ + 1 => ['a' => 36], + ], + ], $m->__debugInfo()); + } + + private function generateRandomString($length = 10) + { + $randomString = str_repeat("+", $length); + for ($i = 0; $i < $length; $i++) { + $randomString[$i] = chr(rand(0, 255)); + } + return $randomString; + } +} diff --git a/pkg/cc_dist_library.bzl b/pkg/cc_dist_library.bzl index 42553ca3f8..9fc2c414e6 100644 --- a/pkg/cc_dist_library.bzl +++ b/pkg/cc_dist_library.bzl @@ -170,12 +170,12 @@ def _cc_file_list_aspect_impl(target, ctx): return [CcFileList( hdrs = _get_transitive_sources( - _flatten_target_files(rule_attr.hdrs).to_list(), + _flatten_target_files(getattr(rule_attr, "hdrs", [])).to_list(), "hdrs", rule_attr.deps, ), textual_hdrs = _get_transitive_sources( - _flatten_target_files(rule_attr.textual_hdrs).to_list(), + _flatten_target_files(getattr(rule_attr, "textual_hdrs", [])).to_list(), "textual_hdrs", rule_attr.deps, ), diff --git a/protos_generator/tests/BUILD b/protos_generator/tests/BUILD index e5c203f229..e4b236626f 100644 --- a/protos_generator/tests/BUILD +++ b/protos_generator/tests/BUILD @@ -11,7 +11,7 @@ load( ) load( "//bazel:upb_proto_library.bzl", - "upb_proto_library", + "upb_c_proto_library", ) load( "//protos/bazel:upb_cc_proto_library.bzl", @@ -60,7 +60,7 @@ proto_library( deps = [":no_package_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "test_model_upb_proto", visibility = [ "//protos:__pkg__", diff --git a/protos_generator/tests/test_generated.cc b/protos_generator/tests/test_generated.cc index 1206b6a998..121251b6a7 100644 --- a/protos_generator/tests/test_generated.cc +++ b/protos_generator/tests/test_generated.cc @@ -114,7 +114,7 @@ TEST(CppGeneratedCode, ScalarInt32) { // Test int32 defaults. EXPECT_EQ(testModel.value(), 0); EXPECT_FALSE(testModel.has_value()); - // Floating point defautls. + // Floating point defaults. EXPECT_EQ(std::numeric_limits::infinity(), testModel.float_value_with_default()); EXPECT_EQ(-std::numeric_limits::infinity(), diff --git a/python/dist/BUILD.bazel b/python/dist/BUILD.bazel index 4330fe1c4f..ba549acb25 100644 --- a/python/dist/BUILD.bazel +++ b/python/dist/BUILD.bazel @@ -246,6 +246,7 @@ pkg_files( "//upb/mini_descriptor:source_files", "//upb/mini_table:source_files", "//upb/port:source_files", + "//upb/reflection:source_files", "//upb/text:source_files", "//upb/util:source_files", "//upb/wire:source_files", diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py index 65caf63f8b..09af96e67c 100755 --- a/python/google/protobuf/internal/api_implementation.py +++ b/python/google/protobuf/internal/api_implementation.py @@ -13,6 +13,8 @@ import os import sys import warnings +_GOOGLE3_PYTHON_UPB_DEFAULT = False + def _ApiVersionToImplementationType(api_version): if api_version == 2: diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index 1adbad286e..56ca079f34 100755 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -12,13 +12,15 @@ __author__ = 'robinson@google.com (Will Robinson)' import unittest import warnings -from google.protobuf import descriptor_pb2 -from google.protobuf.internal import api_implementation -from google.protobuf.internal import test_util from google.protobuf import descriptor +from google.protobuf import descriptor_pb2 from google.protobuf import descriptor_pool from google.protobuf import symbol_database from google.protobuf import text_format +from google.protobuf.internal import api_implementation +from google.protobuf.internal import test_util + +from google.protobuf.internal import _parameterized from google.protobuf import unittest_custom_options_pb2 from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_pb2 @@ -1169,7 +1171,6 @@ class MakeDescriptorTest(unittest.TestCase): self.assertEqual(result.fields[0].cpp_type, descriptor.FieldDescriptor.CPPTYPE_UINT64) - def testMakeDescriptorWithOptions(self): descriptor_proto = descriptor_pb2.DescriptorProto() aggregate_message = unittest_custom_options_pb2.AggregateMessage @@ -1214,5 +1215,63 @@ class MakeDescriptorTest(unittest.TestCase): json_names[index]) +class FeaturesTest(_parameterized.TestCase): + + # TODO Add _features for upb and C++. + @_parameterized.named_parameters([ + ('File', lambda: descriptor_pb2.DESCRIPTOR), + ('Message', lambda: descriptor_pb2.FeatureSet.DESCRIPTOR), + ( + 'Enum', + lambda: descriptor_pb2.FeatureSet.FieldPresence.DESCRIPTOR, + ), + ( + 'Field', + lambda: descriptor_pb2.FeatureSet.DESCRIPTOR.fields_by_name[ + 'enum_type' + ], + ), + ]) + @unittest.skipIf( + api_implementation.Type() != 'python', + 'Features field is only available with the pure python implementation', + ) + def testDescriptorProtoDefaultFeatures(self, desc): + self.assertEqual( + desc()._features.field_presence, + descriptor_pb2.FeatureSet.FieldPresence.EXPLICIT, + ) + self.assertEqual( + desc()._features.enum_type, + descriptor_pb2.FeatureSet.EnumType.CLOSED, + ) + self.assertEqual( + desc()._features.repeated_field_encoding, + descriptor_pb2.FeatureSet.RepeatedFieldEncoding.EXPANDED, + ) + + # TODO Add _features for upb and C++. + @unittest.skipIf( + api_implementation.Type() != 'python', + 'Features field is only available with the pure python implementation', + ) + def testDescriptorProtoOverrideFeatures(self): + desc = descriptor_pb2.SourceCodeInfo.Location.DESCRIPTOR.fields_by_name[ + 'path' + ] + self.assertEqual( + desc._features.field_presence, + descriptor_pb2.FeatureSet.FieldPresence.EXPLICIT, + ) + self.assertEqual( + desc._features.enum_type, + descriptor_pb2.FeatureSet.EnumType.CLOSED, + ) + self.assertEqual( + desc._features.repeated_field_encoding, + descriptor_pb2.FeatureSet.RepeatedFieldEncoding.PACKED, + ) + + if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 2230d0c94d..1f22b86458 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -1462,6 +1462,7 @@ class Proto2ReflectionTest(unittest.TestCase): if api_implementation.Type() != 'python': return + file = descriptor.FileDescriptor(name='foo.proto', package='') FieldDescriptor = descriptor.FieldDescriptor foo_field_descriptor = FieldDescriptor( name='foo_field', full_name='MyProto.foo_field', @@ -1470,7 +1471,7 @@ class Proto2ReflectionTest(unittest.TestCase): label=FieldDescriptor.LABEL_OPTIONAL, default_value=0, containing_type=None, message_type=None, enum_type=None, is_extension=False, extension_scope=None, - options=descriptor_pb2.FieldOptions(), + options=descriptor_pb2.FieldOptions(), file=file, # pylint: disable=protected-access create_key=descriptor._internal_create_key) mydescriptor = descriptor.Descriptor( @@ -1478,6 +1479,7 @@ class Proto2ReflectionTest(unittest.TestCase): containing_type=None, nested_types=[], enum_types=[], fields=[foo_field_descriptor], extensions=[], options=descriptor_pb2.MessageOptions(), + file=file, # pylint: disable=protected-access create_key=descriptor._internal_create_key) diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index 8f9d5f8862..75f3b5b35a 100644 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -854,10 +854,11 @@ class TextFormatParserTests(TextFormatBase): # itself for string fields. It also demonstrates escaped binary data. # The ur"" string prefix is unfortunately missing from Python 3 # so we resort to double escaping our \s so that they come through. - _UNICODE_SAMPLE = u""" + _UNICODE_SAMPLE = """ optional_bytes: 'Á short desçription' optional_string: 'Á short desçription' repeated_bytes: '\\303\\201 short des\\303\\247ription' + repeated_bytes: '\\u00c1 short des\\u00e7ription' repeated_bytes: '\\x12\\x34\\x56\\x78\\x90\\xab\\xcd\\xef' repeated_string: '\\xd0\\x9f\\xd1\\x80\\xd0\\xb8\\xd0\\xb2\\xd0\\xb5\\xd1\\x82' """ @@ -873,8 +874,9 @@ class TextFormatParserTests(TextFormatBase): self.assertEqual(m.optional_bytes, self._GOLDEN_BYTES) self.assertEqual(m.optional_string, self._GOLDEN_UNICODE) self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES) - # repeated_bytes[1] contained simple \ escaped non-UTF-8 raw binary data. - self.assertEqual(m.repeated_bytes[1], self._GOLDEN_BYTES_1) + self.assertEqual(m.repeated_bytes[1], self._GOLDEN_BYTES) + # repeated_bytes[2] contained simple \ escaped non-UTF-8 raw binary data. + self.assertEqual(m.repeated_bytes[2], self._GOLDEN_BYTES_1) # repeated_string[0] contained \ escaped data representing the UTF-8 # representation of _GOLDEN_STR_0 - it needs to decode as such. self.assertEqual(m.repeated_string[0], self._GOLDEN_STR_0) @@ -885,8 +887,9 @@ class TextFormatParserTests(TextFormatBase): self.assertEqual(m.optional_bytes, self._GOLDEN_BYTES) self.assertEqual(m.optional_string, self._GOLDEN_UNICODE) self.assertEqual(m.repeated_bytes[0], self._GOLDEN_BYTES) + self.assertEqual(m.repeated_bytes[1], self._GOLDEN_BYTES) # repeated_bytes[1] contained simple \ escaped non-UTF-8 raw binary data. - self.assertEqual(m.repeated_bytes[1], self._GOLDEN_BYTES_1) + self.assertEqual(m.repeated_bytes[2], self._GOLDEN_BYTES_1) # repeated_string[0] contained \ escaped data representing the UTF-8 # representation of _GOLDEN_STR_0 - it needs to decode as such. self.assertEqual(m.repeated_string[0], self._GOLDEN_STR_0) diff --git a/python/google/protobuf/text_encoding.py b/python/google/protobuf/text_encoding.py index d454987496..112e4ab105 100644 --- a/python/google/protobuf/text_encoding.py +++ b/python/google/protobuf/text_encoding.py @@ -79,7 +79,10 @@ def CUnescape(text: str) -> bytes: # allow single-digit hex escapes (like '\xf'). result = _CUNESCAPE_HEX.sub(ReplaceHex, text) - return (result.encode('utf-8') # Make it bytes to allow decode. - .decode('unicode_escape') - # Make it bytes again to return the proper type. - .encode('raw_unicode_escape')) + # Replaces Unicode escape sequences with their character equivalents. + result = result.encode('raw_unicode_escape').decode('raw_unicode_escape') + # Encode Unicode characters as UTF-8, then decode to Latin-1 escaping + # unprintable characters. + result = result.encode('utf-8').decode('unicode_escape') + # Convert Latin-1 text back to a byte string (latin-1 codec also works here). + return result.encode('latin-1') diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c index 902c9c71a6..8790a0e32d 100644 --- a/ruby/ext/google/protobuf_c/ruby-upb.c +++ b/ruby/ext/google/protobuf_c/ruby-upb.c @@ -5318,8 +5318,10 @@ bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) { } } -void upb_Arena_IncRefFor(upb_Arena* arena, const void* owner) { +bool upb_Arena_IncRefFor(upb_Arena* arena, const void* owner) { _upb_ArenaRoot r; + if (upb_Arena_HasInitialBlock(arena)) return false; + retry: r = _upb_Arena_FindRoot(arena); if (upb_Atomic_CompareExchangeWeak( @@ -5328,7 +5330,7 @@ retry: _upb_Arena_RefCountFromTagged(r.tagged_count) + 1), memory_order_release, memory_order_acquire)) { // We incremented it successfully, so we are done. - return; + return true; } // We failed update due to parent switching on the arena. goto retry; diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h index c4be0d71dd..9393812f7e 100755 --- a/ruby/ext/google/protobuf_c/ruby-upb.h +++ b/ruby/ext/google/protobuf_c/ruby-upb.h @@ -563,7 +563,7 @@ UPB_API upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc); UPB_API void upb_Arena_Free(upb_Arena* a); UPB_API bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b); -void upb_Arena_IncRefFor(upb_Arena* arena, const void* owner); +bool upb_Arena_IncRefFor(upb_Arena* arena, const void* owner); void upb_Arena_DecRefFor(upb_Arena* arena, const void* owner); void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size); diff --git a/rust/BUILD b/rust/BUILD index dd23b44abe..3e0ca71ed6 100644 --- a/rust/BUILD +++ b/rust/BUILD @@ -52,6 +52,7 @@ PROTOBUF_SHARED = [ "optional.rs", "primitive.rs", "proxied.rs", + "repeated.rs", "shared.rs", "string.rs", "vtable.rs", @@ -92,8 +93,14 @@ rust_library( name = "protobuf_cpp", srcs = PROTOBUF_SHARED + ["cpp.rs"], crate_root = "shared.rs", + proc_macro_deps = [ + "@crate_index//:paste", + ], rustc_flags = ["--cfg=cpp_kernel"], - deps = [":utf8"], + deps = [ + ":utf8", + "//rust/cpp_kernel:cpp_api", + ], ) rust_test( diff --git a/rust/aspects.bzl b/rust/aspects.bzl index d0c877db0d..68a590e76a 100644 --- a/rust/aspects.bzl +++ b/rust/aspects.bzl @@ -8,7 +8,6 @@ load("@rules_rust//rust/private:providers.bzl", "CrateInfo", "DepInfo", "DepVari # buildifier: disable=bzl-visibility load("@rules_rust//rust/private:rustc.bzl", "rustc_compile_action") -load("@rules_rust//rust:defs.bzl", "rust_common") load("//bazel:upb_proto_library.bzl", "UpbWrappedCcInfo", "upb_proto_library_aspect") load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") @@ -173,7 +172,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps): ctx = ctx, attr = attr, toolchain = toolchain, - crate_info = rust_common.create_crate_info( + crate_info_dict = dict( name = crate_name, type = "rlib", root = src, diff --git a/rust/cpp.rs b/rust/cpp.rs index c2af02d7c0..7c4998f875 100644 --- a/rust/cpp.rs +++ b/rust/cpp.rs @@ -7,7 +7,8 @@ // Rust Protobuf runtime using the C++ kernel. -use crate::__internal::{Private, RawArena, RawMessage}; +use crate::__internal::{Private, RawArena, RawMessage, RawRepeatedField}; +use paste::paste; use std::alloc::Layout; use std::cell::UnsafeCell; use std::fmt; @@ -35,6 +36,7 @@ pub struct Arena { impl Arena { /// Allocates a fresh arena. #[inline] + #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { ptr: NonNull::dangling(), _not_sync: PhantomData } } @@ -182,6 +184,133 @@ pub fn copy_bytes_in_arena_if_needed_by_runtime<'a>( val } +/// RepeatedField impls delegate out to `extern "C"` functions exposed by +/// `cpp_api.h` and store either a RepeatedField* or a RepeatedPtrField* +/// depending on the type. +/// +/// Note: even though this type is `Copy`, it should only be copied by +/// protobuf internals that can maintain mutation invariants: +/// +/// - No concurrent mutation for any two fields in a message: this means +/// mutators cannot be `Send` but are `Sync`. +/// - If there are multiple accessible `Mut` to a single message at a time, they +/// must be different fields, and not be in the same oneof. As such, a `Mut` +/// cannot be `Clone` but *can* reborrow itself with `.as_mut()`, which +/// converts `&'b mut Mut<'a, T>` to `Mut<'b, T>`. +#[derive(Debug)] +pub struct RepeatedField<'msg, T: ?Sized> { + inner: RepeatedFieldInner<'msg>, + _phantom: PhantomData<&'msg mut T>, +} + +/// CPP runtime-specific arguments for initializing a RepeatedField. +/// See RepeatedField comment about mutation invariants for when this type can +/// be copied. +#[derive(Clone, Copy, Debug)] +pub struct RepeatedFieldInner<'msg> { + pub raw: RawRepeatedField, + pub _phantom: PhantomData<&'msg ()>, +} + +impl<'msg, T: ?Sized> RepeatedField<'msg, T> { + pub fn from_inner(_private: Private, inner: RepeatedFieldInner<'msg>) -> Self { + RepeatedField { inner, _phantom: PhantomData } + } +} + +// These use manual impls instead of derives to avoid unnecessary bounds on `T`. +// This problem is referred to as "perfect derive". +// https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/ +impl<'msg, T: ?Sized> Copy for RepeatedField<'msg, T> {} +impl<'msg, T: ?Sized> Clone for RepeatedField<'msg, T> { + fn clone(&self) -> RepeatedField<'msg, T> { + *self + } +} + +pub trait RepeatedScalarOps { + fn new_repeated_field() -> RawRepeatedField; + fn push(f: RawRepeatedField, v: Self); + fn len(f: RawRepeatedField) -> usize; + fn get(f: RawRepeatedField, i: usize) -> Self; + fn set(f: RawRepeatedField, i: usize, v: Self); + fn copy_from(src: RawRepeatedField, dst: RawRepeatedField); +} + +macro_rules! impl_repeated_scalar_ops { + ($($t: ty),*) => { + paste! { $( + extern "C" { + fn [< __pb_rust_RepeatedField_ $t _new >]() -> RawRepeatedField; + fn [< __pb_rust_RepeatedField_ $t _add >](f: RawRepeatedField, v: $t); + fn [< __pb_rust_RepeatedField_ $t _size >](f: RawRepeatedField) -> usize; + fn [< __pb_rust_RepeatedField_ $t _get >](f: RawRepeatedField, i: usize) -> $t; + fn [< __pb_rust_RepeatedField_ $t _set >](f: RawRepeatedField, i: usize, v: $t); + fn [< __pb_rust_RepeatedField_ $t _copy_from >](src: RawRepeatedField, dst: RawRepeatedField); + } + impl RepeatedScalarOps for $t { + fn new_repeated_field() -> RawRepeatedField { + unsafe { [< __pb_rust_RepeatedField_ $t _new >]() } + } + fn push(f: RawRepeatedField, v: Self) { + unsafe { [< __pb_rust_RepeatedField_ $t _add >](f, v) } + } + fn len(f: RawRepeatedField) -> usize { + unsafe { [< __pb_rust_RepeatedField_ $t _size >](f) } + } + fn get(f: RawRepeatedField, i: usize) -> Self { + unsafe { [< __pb_rust_RepeatedField_ $t _get >](f, i) } + } + fn set(f: RawRepeatedField, i: usize, v: Self) { + unsafe { [< __pb_rust_RepeatedField_ $t _set >](f, i, v) } + } + fn copy_from(src: RawRepeatedField, dst: RawRepeatedField) { + unsafe { [< __pb_rust_RepeatedField_ $t _copy_from >](src, dst) } + } + } + )* } + }; +} + +impl_repeated_scalar_ops!(i32, u32, i64, u64, f32, f64, bool); + +impl<'msg, T: RepeatedScalarOps> RepeatedField<'msg, T> { + #[allow(clippy::new_without_default, dead_code)] + /// new() is not currently used in our normal pathways, it is only used + /// for testing. Existing `RepeatedField<>`s are owned by, and retrieved + /// from, the containing `Message`. + pub fn new() -> Self { + Self::from_inner( + Private, + RepeatedFieldInner::<'msg> { raw: T::new_repeated_field(), _phantom: PhantomData }, + ) + } + pub fn push(&mut self, val: T) { + T::push(self.inner.raw, val) + } + pub fn len(&self) -> usize { + T::len(self.inner.raw) + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, index: usize) -> Option { + if index >= self.len() { + return None; + } + Some(T::get(self.inner.raw, index)) + } + pub fn set(&mut self, index: usize, val: T) { + if index >= self.len() { + return; + } + T::set(self.inner.raw, index, val) + } + pub fn copy_from(&mut self, src: &RepeatedField<'_, T>) { + T::copy_from(src.inner.raw, self.inner.raw) + } +} + #[cfg(test)] mod tests { use super::*; @@ -201,4 +330,27 @@ mod tests { let serialized_data = SerializedData { data: NonNull::new(ptr).unwrap(), len: len }; assert_eq!(&*serialized_data, b"Hello world"); } + + #[test] + fn repeated_field() { + let mut r = RepeatedField::::new(); + assert_eq!(r.len(), 0); + r.push(32); + assert_eq!(r.get(0), Some(32)); + + let mut r = RepeatedField::::new(); + assert_eq!(r.len(), 0); + r.push(32); + assert_eq!(r.get(0), Some(32)); + + let mut r = RepeatedField::::new(); + assert_eq!(r.len(), 0); + r.push(0.1234f64); + assert_eq!(r.get(0), Some(0.1234)); + + let mut r = RepeatedField::::new(); + assert_eq!(r.len(), 0); + r.push(true); + assert_eq!(r.get(0), Some(true)); + } } diff --git a/rust/cpp_kernel/BUILD b/rust/cpp_kernel/BUILD index 245772c834..d10f9e7db8 100644 --- a/rust/cpp_kernel/BUILD +++ b/rust/cpp_kernel/BUILD @@ -4,13 +4,14 @@ load("@rules_rust//rust:defs.bzl", "rust_library") cc_library( name = "cpp_api", + srcs = ["cpp_api.cc"], hdrs = ["cpp_api.h"], visibility = [ "//src/google/protobuf:__subpackages__", "//rust:__subpackages__", ], deps = [ - ":rust_alloc_for_cpp_api", + ":rust_alloc_for_cpp_api", # buildcleaner: keep "//:protobuf_nowkt", ], ) diff --git a/rust/cpp_kernel/cpp_api.cc b/rust/cpp_kernel/cpp_api.cc new file mode 100644 index 0000000000..1381611064 --- /dev/null +++ b/rust/cpp_kernel/cpp_api.cc @@ -0,0 +1,39 @@ +#include "google/protobuf/repeated_field.h" + +extern "C" { + +#define expose_repeated_field_methods(ty, rust_ty) \ + google::protobuf::RepeatedField* __pb_rust_RepeatedField_##rust_ty##_new() { \ + return new google::protobuf::RepeatedField(); \ + } \ + void __pb_rust_RepeatedField_##rust_ty##_add(google::protobuf::RepeatedField* r, \ + ty val) { \ + r->Add(val); \ + } \ + size_t __pb_rust_RepeatedField_##rust_ty##_size( \ + google::protobuf::RepeatedField* r) { \ + return r->size(); \ + } \ + ty __pb_rust_RepeatedField_##rust_ty##_get(google::protobuf::RepeatedField* r, \ + size_t index) { \ + return r->Get(index); \ + } \ + void __pb_rust_RepeatedField_##rust_ty##_set(google::protobuf::RepeatedField* r, \ + size_t index, ty val) { \ + return r->Set(index, val); \ + } \ + void __pb_rust_RepeatedField_##rust_ty##_copy_from( \ + google::protobuf::RepeatedField const& src, google::protobuf::RepeatedField& dst) { \ + dst.CopyFrom(src); \ + } + +expose_repeated_field_methods(int32_t, i32); +expose_repeated_field_methods(uint32_t, u32); +expose_repeated_field_methods(float, f32); +expose_repeated_field_methods(double, f64); +expose_repeated_field_methods(bool, bool); +expose_repeated_field_methods(uint64_t, u64); +expose_repeated_field_methods(int64_t, i64); + +#undef expose_repeated_field_methods +} diff --git a/rust/internal.rs b/rust/internal.rs index 1e0f536b19..d7ea96baaf 100644 --- a/rust/internal.rs +++ b/rust/internal.rs @@ -10,8 +10,8 @@ //! generated code. pub use crate::vtable::{ - new_vtable_field_entry, BytesMutVTable, BytesOptionalMutVTable, PrimitiveVTable, - RawVTableMutator, + new_vtable_field_entry, BytesMutVTable, BytesOptionalMutVTable, PrimitiveOptionalMutVTable, + PrimitiveVTable, RawVTableMutator, }; use std::ptr::NonNull; use std::slice; @@ -51,6 +51,17 @@ mod _opaque_pointees { _data: [u8; 0], _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>, } + + /// Opaque pointee for [`RawRepeatedField`] + /// + /// This type is not meant to be dereferenced in Rust code. + /// It is only meant to provide type safety for raw pointers + /// which are manipulated behind FFI. + #[repr(C)] + pub struct RawRepeatedFieldData { + _data: [u8; 0], + _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>, + } } /// A raw pointer to the underlying message for this runtime. @@ -59,6 +70,9 @@ pub type RawMessage = NonNull<_opaque_pointees::RawMessageData>; /// A raw pointer to the underlying arena for this runtime. pub type RawArena = NonNull<_opaque_pointees::RawArenaData>; +/// A raw pointer to the underlying repeated field container for this runtime. +pub type RawRepeatedField = NonNull<_opaque_pointees::RawRepeatedFieldData>; + /// Represents an ABI-stable version of `NonNull<[u8]>`/`string_view` (a /// borrowed slice of bytes) for FFI use only. /// diff --git a/rust/primitive.rs b/rust/primitive.rs index 220b84e469..dd2fec18d4 100644 --- a/rust/primitive.rs +++ b/rust/primitive.rs @@ -7,22 +7,39 @@ use crate::__internal::Private; use crate::__runtime::InnerPrimitiveMut; -use crate::vtable::{PrimitiveVTable, ProxiedWithRawVTable}; -use crate::{Mut, MutProxy, Proxied, SettableValue, View, ViewProxy}; +use crate::repeated::RepeatedMut; +use crate::vtable::{ + PrimitiveOptionalMutVTable, PrimitiveVTable, ProxiedWithRawOptionalVTable, + ProxiedWithRawVTable, RawVTableOptionalMutatorData, +}; +use crate::{Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy}; #[derive(Debug)] -pub struct PrimitiveMut<'a, T: ProxiedWithRawVTable> { +pub struct SingularPrimitiveMut<'a, T: ProxiedWithRawVTable> { inner: InnerPrimitiveMut<'a, T>, } +#[derive(Debug)] +pub enum PrimitiveMut<'a, T: ProxiedWithRawVTable> { + Singular(SingularPrimitiveMut<'a, T>), + Repeated(RepeatedMut<'a, T>, usize), +} + impl<'a, T: ProxiedWithRawVTable> PrimitiveMut<'a, T> { + #[doc(hidden)] + pub fn from_singular(_private: Private, inner: InnerPrimitiveMut<'a, T>) -> Self { + PrimitiveMut::Singular(SingularPrimitiveMut::from_inner(_private, inner)) + } +} + +impl<'a, T: ProxiedWithRawVTable> SingularPrimitiveMut<'a, T> { #[doc(hidden)] pub fn from_inner(_private: Private, inner: InnerPrimitiveMut<'a, T>) -> Self { Self { inner } } } -unsafe impl<'a, T: ProxiedWithRawVTable> Sync for PrimitiveMut<'a, T> {} +unsafe impl<'a, T: ProxiedWithRawVTable> Sync for SingularPrimitiveMut<'a, T> {} macro_rules! impl_singular_primitives { ($($t:ty),*) => { @@ -44,6 +61,29 @@ macro_rules! impl_singular_primitives { } } + impl<'a> PrimitiveMut<'a, $t> { + pub fn get(&self) -> View<'_, $t> { + match self { + PrimitiveMut::Singular(s) => { + s.get() + } + PrimitiveMut::Repeated(r, i) => { + r.get().get(*i).unwrap() + } + } + } + + pub fn set(&mut self, val: impl SettableValue<$t>) { + val.set_on(Private, self.as_mut()); + } + + pub fn clear(&mut self) { + // The default value for a boolean field is false and 0 for numerical types. It + // matches the Rust default values for corresponding types. Let's use this fact. + SettableValue::<$t>::set_on(<$t>::default(), Private, MutProxy::as_mut(self)); + } + } + impl<'a> ViewProxy<'a> for PrimitiveMut<'a, $t> { type Proxied = $t; @@ -58,7 +98,14 @@ macro_rules! impl_singular_primitives { impl<'a> MutProxy<'a> for PrimitiveMut<'a, $t> { fn as_mut(&mut self) -> Mut<'_, Self::Proxied> { - PrimitiveMut::from_inner(Private, self.inner) + match self { + PrimitiveMut::Singular(s) => { + PrimitiveMut::Singular(s.as_mut()) + } + PrimitiveMut::Repeated(r, i) => { + PrimitiveMut::Repeated(r.as_mut(), *i) + } + } } fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied> @@ -70,23 +117,23 @@ macro_rules! impl_singular_primitives { impl SettableValue<$t> for $t { fn set_on(self, _private: Private, mutator: Mut<'_, $t>) { - unsafe { (mutator.inner).set(self) }; + match mutator { + PrimitiveMut::Singular(s) => { + unsafe { (s.inner).set(self) }; + } + PrimitiveMut::Repeated(mut r, i) => { + r.set(i, self); + } + } } } - impl<'a> PrimitiveMut<'a, $t> { - pub fn set(&mut self, val: impl SettableValue<$t>) { - val.set_on(Private, self.as_mut()); - } - + impl<'a> SingularPrimitiveMut<'a, $t> { pub fn get(&self) -> $t { self.inner.get() } - - pub fn clear(&mut self) { - // The default value for a boolean field is false and 0 for numerical types. It - // matches the Rust default values for corresponding types. Let's use this fact. - SettableValue::<$t>::set_on(<$t>::default(), Private, MutProxy::as_mut(self)); + pub fn as_mut(&mut self) -> SingularPrimitiveMut<'_, $t> { + SingularPrimitiveMut::from_inner(Private, self.inner) } } @@ -101,7 +148,35 @@ macro_rules! impl_singular_primitives { } fn make_mut(_private: Private, inner: InnerPrimitiveMut<'_, Self>) -> Mut<'_, Self> { - PrimitiveMut::from_inner(Private, inner) + PrimitiveMut::Singular(SingularPrimitiveMut::from_inner(Private, inner)) + } + } + + impl ProxiedWithPresence for $t { + type PresentMutData<'a> = RawVTableOptionalMutatorData<'a, $t>; + type AbsentMutData<'a> = RawVTableOptionalMutatorData<'a, $t>; + + fn clear_present_field( + present_mutator: Self::PresentMutData<'_>, + ) -> Self::AbsentMutData<'_> { + present_mutator.clear() + } + + fn set_absent_to_default( + absent_mutator: Self::AbsentMutData<'_>, + ) -> Self::PresentMutData<'_> { + absent_mutator.set_absent_to_default() + } + } + + impl ProxiedWithRawOptionalVTable for $t { + type OptionalVTable = PrimitiveOptionalMutVTable<$t>; + + fn upcast_vtable( + _private: Private, + optional_vtable: &'static Self::OptionalVTable, + ) -> &'static Self::VTable { + &optional_vtable.base } } )* diff --git a/rust/repeated.rs b/rust/repeated.rs new file mode 100644 index 0000000000..1abb7152ba --- /dev/null +++ b/rust/repeated.rs @@ -0,0 +1,233 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2023 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +/// Repeated scalar fields are implemented around the runtime-specific +/// `RepeatedField` struct. `RepeatedField` stores an opaque pointer to the +/// runtime-specific representation of a repeated scalar (`upb_Array*` on upb, +/// and `RepeatedField*` on cpp). +use std::marker::PhantomData; + +use crate::{ + Mut, MutProxy, Proxied, SettableValue, View, ViewProxy, + __internal::{Private, RawRepeatedField}, + __runtime::{RepeatedField, RepeatedFieldInner}, + primitive::PrimitiveMut, + vtable::ProxiedWithRawVTable, +}; + +#[derive(Clone, Copy)] +pub struct RepeatedFieldRef<'a> { + pub repeated_field: RawRepeatedField, + pub _phantom: PhantomData<&'a mut ()>, +} + +unsafe impl<'a> Send for RepeatedFieldRef<'a> {} +unsafe impl<'a> Sync for RepeatedFieldRef<'a> {} + +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct RepeatedView<'a, T: ?Sized> { + inner: RepeatedField<'a, T>, +} + +unsafe impl<'a, T: ProxiedWithRawVTable> Sync for RepeatedView<'a, T> {} +unsafe impl<'a, T: ProxiedWithRawVTable> Send for RepeatedView<'a, T> {} + +impl<'msg, T: ?Sized> RepeatedView<'msg, T> { + pub fn from_inner(_private: Private, inner: RepeatedFieldInner<'msg>) -> Self { + Self { inner: RepeatedField::<'msg>::from_inner(_private, inner) } + } +} + +pub struct RepeatedFieldIter<'a, T> { + inner: RepeatedField<'a, T>, + current_index: usize, +} + +impl<'a, T> std::fmt::Debug for RepeatedView<'a, T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("RepeatedView").finish() + } +} + +#[repr(transparent)] +#[derive(Debug)] +pub struct RepeatedMut<'a, T: ?Sized> { + inner: RepeatedField<'a, T>, +} + +unsafe impl<'a, T: ProxiedWithRawVTable> Sync for RepeatedMut<'a, T> {} + +impl<'msg, T: ?Sized> RepeatedMut<'msg, T> { + pub fn from_inner(_private: Private, inner: RepeatedFieldInner<'msg>) -> Self { + Self { inner: RepeatedField::from_inner(_private, inner) } + } + pub fn as_mut(&self) -> RepeatedMut<'_, T> { + Self { inner: self.inner } + } +} + +impl<'a, T> std::ops::Deref for RepeatedMut<'a, T> { + type Target = RepeatedView<'a, T>; + fn deref(&self) -> &Self::Target { + // SAFETY: + // - `Repeated{View,Mut}<'a, T>` are both `#[repr(transparent)]` over + // `RepeatedField<'a, T>`. + // - `RepeatedField` is a type alias for `NonNull`. + unsafe { &*(self as *const Self as *const RepeatedView<'a, T>) } + } +} + +pub struct RepeatedFieldIterMut<'a, T> { + inner: RepeatedMut<'a, T>, + current_index: usize, +} + +pub struct Repeated(PhantomData); + +macro_rules! impl_repeated_primitives { + ($($t:ty),*) => { + $( + impl Proxied for Repeated<$t> { + type View<'a> = RepeatedView<'a, $t>; + type Mut<'a> = RepeatedMut<'a, $t>; + } + + impl<'a> ViewProxy<'a> for RepeatedView<'a, $t> { + type Proxied = Repeated<$t>; + + fn as_view(&self) -> View<'_, Self::Proxied> { + *self + } + + fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> + where 'a: 'shorter, + { + RepeatedView { inner: self.inner } + } + } + + impl<'a> ViewProxy<'a> for RepeatedMut<'a, $t> { + type Proxied = Repeated<$t>; + + fn as_view(&self) -> View<'_, Self::Proxied> { + **self + } + + fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> + where 'a: 'shorter, + { + *self.into_mut::<'shorter>() + } + } + + impl<'a> MutProxy<'a> for RepeatedMut<'a, $t> { + fn as_mut(&mut self) -> Mut<'_, Self::Proxied> { + RepeatedMut { inner: self.inner } + } + + fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied> + where 'a: 'shorter, + { + RepeatedMut { inner: self.inner } + } + } + + impl <'a> SettableValue> for RepeatedView<'a, $t> { + fn set_on(self, _private: Private, mut mutator: Mut<'_, Repeated<$t>>) { + mutator.copy_from(self); + } + } + + impl<'a> RepeatedView<'a, $t> { + pub fn len(&self) -> usize { + self.inner.len() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, index: usize) -> Option<$t> { + self.inner.get(index) + } + pub fn iter(&self) -> RepeatedFieldIter<'_, $t> { + (*self).into_iter() + } + } + + impl<'a> RepeatedMut<'a, $t> { + pub fn push(&mut self, val: $t) { + self.inner.push(val) + } + pub fn set(&mut self, index: usize, val: $t) { + self.inner.set(index, val) + } + pub fn get_mut(&mut self, index: usize) -> Option> { + if index >= self.len() { + return None; + } + Some(PrimitiveMut::Repeated(self.as_mut(), index)) + } + pub fn iter(&self) -> RepeatedFieldIter<'_, $t> { + self.as_view().into_iter() + } + pub fn iter_mut(&mut self) -> RepeatedFieldIterMut<'_, $t> { + self.as_mut().into_iter() + } + pub fn copy_from(&mut self, src: RepeatedView<'_, $t>) { + self.inner.copy_from(&src.inner); + } + } + + impl<'a> std::iter::Iterator for RepeatedFieldIter<'a, $t> { + type Item = $t; + fn next(&mut self) -> Option { + let val = self.inner.get(self.current_index); + if val.is_some() { + self.current_index += 1; + } + val + } + } + + impl<'a> std::iter::IntoIterator for RepeatedView<'a, $t> { + type Item = $t; + type IntoIter = RepeatedFieldIter<'a, $t>; + fn into_iter(self) -> Self::IntoIter { + RepeatedFieldIter { inner: self.inner, current_index: 0 } + } + } + + impl <'a> std::iter::Iterator for RepeatedFieldIterMut<'a, $t> { + type Item = Mut<'a, $t>; + fn next(&mut self) -> Option { + if self.current_index >= self.inner.len() { + return None; + } + let elem = PrimitiveMut::Repeated( + // While this appears to allow mutable aliasing + // (multiple `Self::Item`s can co-exist), each `Item` + // only references a specific unique index. + RepeatedMut{ inner: self.inner.inner }, + self.current_index, + ); + self.current_index += 1; + Some(elem) + } + } + + impl<'a> std::iter::IntoIterator for RepeatedMut<'a, $t> { + type Item = Mut<'a, $t>; + type IntoIter = RepeatedFieldIterMut<'a, $t>; + fn into_iter(self) -> Self::IntoIter { + RepeatedFieldIterMut { inner: self, current_index: 0 } + } + } + )* + } +} + +impl_repeated_primitives!(i32, u32, bool, f32, f64, i64, u64); diff --git a/rust/shared.rs b/rust/shared.rs index 3c4408d943..7c3a3d163d 100644 --- a/rust/shared.rs +++ b/rust/shared.rs @@ -18,10 +18,11 @@ use std::fmt; #[doc(hidden)] pub mod __public { pub use crate::optional::{AbsentField, FieldEntry, Optional, PresentField}; - pub use crate::primitive::PrimitiveMut; + pub use crate::primitive::{PrimitiveMut, SingularPrimitiveMut}; pub use crate::proxied::{ Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy, }; + pub use crate::repeated::{RepeatedFieldRef, RepeatedMut, RepeatedView}; pub use crate::string::{BytesMut, ProtoStr, ProtoStrMut}; } pub use __public::*; @@ -46,6 +47,7 @@ mod macros; mod optional; mod primitive; mod proxied; +mod repeated; mod string; mod vtable; diff --git a/rust/test/cpp/interop/test_utils.cc b/rust/test/cpp/interop/test_utils.cc index d5c3784df1..5c27a95c9b 100644 --- a/rust/test/cpp/interop/test_utils.cc +++ b/rust/test/cpp/interop/test_utils.cc @@ -8,7 +8,7 @@ #include #include "absl/strings/string_view.h" -#include "google/protobuf/rust/cpp_kernel/cpp_api.h" +#include "rust/cpp_kernel/cpp_api.h" #include "google/protobuf/unittest.pb.h" extern "C" void MutateTestAllTypes(protobuf_unittest::TestAllTypes* msg) { diff --git a/rust/test/shared/BUILD b/rust/test/shared/BUILD index e5be7b7511..73be626f76 100644 --- a/rust/test/shared/BUILD +++ b/rust/test/shared/BUILD @@ -151,6 +151,9 @@ rust_test( "//rust:protobuf_cpp": "protobuf", "//rust/test/shared:matchers_cpp": "matchers", }, + proc_macro_deps = [ + "@crate_index//:paste", + ], tags = [ # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. "not_build:arm", @@ -170,6 +173,9 @@ rust_test( "//rust:protobuf_upb": "protobuf", "//rust/test/shared:matchers_upb": "matchers", }, + proc_macro_deps = [ + "@crate_index//:paste", + ], tags = [ # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. "not_build:arm", @@ -187,15 +193,18 @@ rust_test( srcs = ["accessors_proto3_test.rs"], aliases = { "//rust:protobuf_cpp": "protobuf", + "//rust/test/shared:matchers_cpp": "matchers", }, tags = [ # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. "not_build:arm", ], deps = [ + "//third_party/gtest_rust/googletest", "//rust:protobuf_cpp", "//rust/test:unittest_proto3_cc_rust_proto", "//rust/test:unittest_proto3_optional_cc_rust_proto", + "//rust/test/shared:matchers_cpp", ], ) @@ -204,15 +213,18 @@ rust_test( srcs = ["accessors_proto3_test.rs"], aliases = { "//rust:protobuf_upb": "protobuf", + "//rust/test/shared:matchers_upb": "matchers", }, tags = [ # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. "not_build:arm", ], deps = [ + "//third_party/gtest_rust/googletest", "//rust:protobuf_upb", "//rust/test:unittest_proto3_optional_upb_rust_proto", "//rust/test:unittest_proto3_upb_rust_proto", + "//rust/test/shared:matchers_upb", ], ) @@ -245,11 +257,19 @@ rust_test( rust_test( name = "simple_nested_cpp_test", srcs = ["simple_nested_test.rs"], + tags = [ + # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. + "not_build:arm", + ], deps = ["//rust/test:nested_cc_rust_proto"], ) rust_test( name = "simple_nested_upb_test", srcs = ["simple_nested_test.rs"], + tags = [ + # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. + "not_build:arm", + ], deps = ["//rust/test:nested_upb_rust_proto"], ) diff --git a/rust/test/shared/accessors_proto3_test.rs b/rust/test/shared/accessors_proto3_test.rs index 84d58a9e9c..3eb6e5df61 100644 --- a/rust/test/shared/accessors_proto3_test.rs +++ b/rust/test/shared/accessors_proto3_test.rs @@ -7,6 +7,8 @@ /// Tests covering accessors for singular bool, int32, int64, and bytes fields /// on proto3. +use googletest::prelude::*; +use matchers::{is_set, is_unset}; use protobuf::Optional; use unittest_proto3::proto3_unittest::{TestAllTypes, TestAllTypes_}; use unittest_proto3_optional::proto2_unittest::TestProto3Optional; @@ -14,31 +16,31 @@ use unittest_proto3_optional::proto2_unittest::TestProto3Optional; #[test] fn test_fixed32_accessors() { let mut msg = TestAllTypes::new(); - assert_eq!(msg.optional_fixed32(), 0); - assert_eq!(msg.optional_fixed32_mut().get(), 0); + assert_that!(msg.optional_fixed32(), eq(0)); + assert_that!(msg.optional_fixed32_mut().get(), eq(0)); msg.optional_fixed32_mut().set(42); - assert_eq!(msg.optional_fixed32_mut().get(), 42); - assert_eq!(msg.optional_fixed32(), 42); + assert_that!(msg.optional_fixed32_mut().get(), eq(42)); + assert_that!(msg.optional_fixed32(), eq(42)); msg.optional_fixed32_mut().clear(); - assert_eq!(msg.optional_fixed32(), 0); - assert_eq!(msg.optional_fixed32_mut().get(), 0); + assert_that!(msg.optional_fixed32(), eq(0)); + assert_that!(msg.optional_fixed32_mut().get(), eq(0)); } #[test] fn test_bool_accessors() { let mut msg = TestAllTypes::new(); - assert!(!msg.optional_bool()); - assert!(!msg.optional_bool_mut().get()); + assert_that!(msg.optional_bool(), eq(false)); + assert_that!(msg.optional_bool_mut().get(), eq(false)); msg.optional_bool_mut().set(true); - assert!(msg.optional_bool()); - assert!(msg.optional_bool_mut().get()); + assert_that!(msg.optional_bool(), eq(true)); + assert_that!(msg.optional_bool_mut().get(), eq(true)); msg.optional_bool_mut().clear(); - assert!(!msg.optional_bool()); - assert!(!msg.optional_bool_mut().get()); + assert_that!(msg.optional_bool(), eq(false)); + assert_that!(msg.optional_bool_mut().get(), eq(false)); } #[test] @@ -46,73 +48,73 @@ fn test_bytes_accessors() { let mut msg = TestAllTypes::new(); // Note: even though it's named 'optional_bytes', the field is actually not // proto3 optional, so it does not support presence. - assert_eq!(msg.optional_bytes(), b""); - assert_eq!(msg.optional_bytes_mut().get(), b""); + assert_that!(*msg.optional_bytes(), empty()); + assert_that!(*msg.optional_bytes_mut().get(), empty()); msg.optional_bytes_mut().set(b"accessors_test"); - assert_eq!(msg.optional_bytes(), b"accessors_test"); - assert_eq!(msg.optional_bytes_mut().get(), b"accessors_test"); + assert_that!(msg.optional_bytes(), eq(b"accessors_test")); + assert_that!(msg.optional_bytes_mut().get(), eq(b"accessors_test")); { let s = Vec::from(&b"hello world"[..]); msg.optional_bytes_mut().set(&s[..]); } - assert_eq!(msg.optional_bytes(), b"hello world"); - assert_eq!(msg.optional_bytes_mut().get(), b"hello world"); + assert_that!(msg.optional_bytes(), eq(b"hello world")); + assert_that!(msg.optional_bytes_mut().get(), eq(b"hello world")); msg.optional_bytes_mut().clear(); - assert_eq!(msg.optional_bytes(), b""); - assert_eq!(msg.optional_bytes_mut().get(), b""); + assert_that!(*msg.optional_bytes(), empty()); + assert_that!(*msg.optional_bytes_mut().get(), empty()); msg.optional_bytes_mut().set(b""); - assert_eq!(msg.optional_bytes(), b""); - assert_eq!(msg.optional_bytes_mut().get(), b""); + assert_that!(*msg.optional_bytes(), empty()); + assert_that!(*msg.optional_bytes_mut().get(), empty()); } #[test] fn test_optional_bytes_accessors() { let mut msg = TestProto3Optional::new(); - assert_eq!(msg.optional_bytes(), b""); - assert_eq!(msg.optional_bytes_opt(), Optional::Unset(&b""[..])); - assert_eq!(msg.optional_bytes_mut().get(), b""); - assert!(msg.optional_bytes_mut().is_unset()); + assert_that!(*msg.optional_bytes(), empty()); + assert_that!(msg.optional_bytes_opt(), eq(Optional::Unset(&b""[..]))); + assert_that!(*msg.optional_bytes_mut().get(), empty()); + assert_that!(msg.optional_bytes_mut(), is_unset()); { let s = Vec::from(&b"hello world"[..]); msg.optional_bytes_mut().set(&s[..]); } - assert_eq!(msg.optional_bytes(), b"hello world"); - assert_eq!(msg.optional_bytes_opt(), Optional::Set(&b"hello world"[..])); - assert!(msg.optional_bytes_mut().is_set()); - assert_eq!(msg.optional_bytes_mut().get(), b"hello world"); + assert_that!(msg.optional_bytes(), eq(b"hello world")); + assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"hello world"[..]))); + assert_that!(msg.optional_bytes_mut(), is_set()); + assert_that!(msg.optional_bytes_mut().get(), eq(b"hello world")); msg.optional_bytes_mut().or_default().set(b"accessors_test"); - assert_eq!(msg.optional_bytes(), b"accessors_test"); - assert_eq!(msg.optional_bytes_opt(), Optional::Set(&b"accessors_test"[..])); - assert!(msg.optional_bytes_mut().is_set()); - assert_eq!(msg.optional_bytes_mut().get(), b"accessors_test"); - assert_eq!(msg.optional_bytes_mut().or_default().get(), b"accessors_test"); + assert_that!(msg.optional_bytes(), eq(b"accessors_test")); + assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"accessors_test"[..]))); + assert_that!(msg.optional_bytes_mut(), is_set()); + assert_that!(msg.optional_bytes_mut().get(), eq(b"accessors_test")); + assert_that!(msg.optional_bytes_mut().or_default().get(), eq(b"accessors_test")); msg.optional_bytes_mut().clear(); - assert_eq!(msg.optional_bytes(), b""); - assert_eq!(msg.optional_bytes_opt(), Optional::Unset(&b""[..])); - assert!(msg.optional_bytes_mut().is_unset()); + assert_that!(*msg.optional_bytes(), empty()); + assert_that!(msg.optional_bytes_opt(), eq(Optional::Unset(&b""[..]))); + assert_that!(msg.optional_bytes_mut(), is_unset()); msg.optional_bytes_mut().set(b""); - assert_eq!(msg.optional_bytes(), b""); - assert_eq!(msg.optional_bytes_opt(), Optional::Set(&b""[..])); + assert_that!(*msg.optional_bytes(), empty()); + assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b""[..]))); msg.optional_bytes_mut().clear(); msg.optional_bytes_mut().or_default(); - assert_eq!(msg.optional_bytes(), b""); - assert_eq!(msg.optional_bytes_opt(), Optional::Set(&b""[..])); + assert_that!(*msg.optional_bytes(), empty()); + assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b""[..]))); msg.optional_bytes_mut().or_default().set(b"\xffbinary\x85non-utf8"); - assert_eq!(msg.optional_bytes(), b"\xffbinary\x85non-utf8"); - assert_eq!(msg.optional_bytes_opt(), Optional::Set(&b"\xffbinary\x85non-utf8"[..])); - assert!(msg.optional_bytes_mut().is_set()); - assert_eq!(msg.optional_bytes_mut().get(), b"\xffbinary\x85non-utf8"); - assert_eq!(msg.optional_bytes_mut().or_default().get(), b"\xffbinary\x85non-utf8"); + assert_that!(msg.optional_bytes(), eq(b"\xffbinary\x85non-utf8")); + assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"\xffbinary\x85non-utf8"[..]))); + assert_that!(msg.optional_bytes_mut(), is_set()); + assert_that!(msg.optional_bytes_mut().get(), eq(b"\xffbinary\x85non-utf8")); + assert_that!(msg.optional_bytes_mut().or_default().get(), eq(b"\xffbinary\x85non-utf8")); } #[test] @@ -149,7 +151,7 @@ fn test_optional_string_accessors() { assert_eq!(msg.optional_string(), ""); assert_eq!(msg.optional_string_opt(), Optional::Unset("".into())); assert_eq!(msg.optional_string_mut().get(), ""); - assert!(msg.optional_string_mut().is_unset()); + assert_that!(msg.optional_string_mut(), is_unset()); { let s = String::from("hello world"); @@ -157,20 +159,20 @@ fn test_optional_string_accessors() { } assert_eq!(msg.optional_string(), "hello world"); assert_eq!(msg.optional_string_opt(), Optional::Set("hello world".into())); - assert!(msg.optional_string_mut().is_set()); + assert_that!(msg.optional_string_mut(), is_set()); assert_eq!(msg.optional_string_mut().get(), "hello world"); msg.optional_string_mut().or_default().set("accessors_test"); assert_eq!(msg.optional_string(), "accessors_test"); assert_eq!(msg.optional_string_opt(), Optional::Set("accessors_test".into())); - assert!(msg.optional_string_mut().is_set()); + assert_that!(msg.optional_string_mut(), is_set()); assert_eq!(msg.optional_string_mut().get(), "accessors_test"); assert_eq!(msg.optional_string_mut().or_default().get(), "accessors_test"); msg.optional_string_mut().clear(); assert_eq!(msg.optional_string(), ""); assert_eq!(msg.optional_string_opt(), Optional::Unset("".into())); - assert!(msg.optional_string_mut().is_unset()); + assert_that!(msg.optional_string_mut(), is_unset()); msg.optional_string_mut().set(""); assert_eq!(msg.optional_string(), ""); @@ -187,20 +189,19 @@ fn test_oneof_accessors() { use TestAllTypes_::OneofField::*; let mut msg = TestAllTypes::new(); - assert!(matches!(msg.oneof_field(), not_set(_))); + assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); msg.oneof_uint32_set(Some(7)); - assert_eq!(msg.oneof_uint32_opt(), Optional::Set(7)); - assert!(matches!(msg.oneof_field(), OneofUint32(7))); + assert_that!(msg.oneof_uint32_opt(), eq(Optional::Set(7))); + assert_that!(msg.oneof_field(), matches_pattern!(OneofUint32(eq(7)))); msg.oneof_uint32_set(None); - assert_eq!(msg.oneof_uint32_opt(), Optional::Unset(0)); - assert!(matches!(msg.oneof_field(), not_set(_))); + assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0))); + assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); msg.oneof_uint32_set(Some(7)); - msg.oneof_bytes_mut().set(b""); - assert_eq!(msg.oneof_uint32_opt(), Optional::Unset(0)); + msg.oneof_bytes_mut().set(b"123"); + assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0))); - // This should show it set to the OneofBytes but its not supported yet. - assert!(matches!(msg.oneof_field(), not_set(_))); + assert_that!(msg.oneof_field(), matches_pattern!(OneofBytes(eq(b"123")))); } diff --git a/rust/test/shared/accessors_test.rs b/rust/test/shared/accessors_test.rs index 40098b18ef..2b207ac11c 100644 --- a/rust/test/shared/accessors_test.rs +++ b/rust/test/shared/accessors_test.rs @@ -9,6 +9,7 @@ use googletest::prelude::*; use matchers::{is_set, is_unset}; +use paste::paste; use protobuf::Optional; use unittest_proto::proto2_unittest::{TestAllTypes, TestAllTypes_}; @@ -50,6 +51,33 @@ fn test_optional_fixed32_accessors() { assert_that!(msg.optional_fixed32(), eq(0)); } +#[test] +fn test_default_fixed32_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_fixed32(), eq(47)); + assert_that!(msg.default_fixed32_mut().get(), eq(47)); + assert_that!(msg.default_fixed32_mut().is_set(), eq(false)); + assert_that!(msg.default_fixed32_opt(), eq(Optional::Unset(47))); + + msg.default_fixed32_mut().set(999); + assert_that!(msg.default_fixed32(), eq(999)); + assert_that!(msg.default_fixed32_mut().get(), eq(999)); + assert_that!(msg.default_fixed32_mut().is_set(), eq(true)); + assert_that!(msg.default_fixed32_opt(), eq(Optional::Set(999))); + + msg.default_fixed32_mut().clear(); + assert_that!(msg.default_fixed32(), eq(47)); + assert_that!(msg.default_fixed32_mut().get(), eq(47)); + assert_that!(msg.default_fixed32_mut().is_set(), eq(false)); + assert_that!(msg.default_fixed32_opt(), eq(Optional::Unset(47))); + + msg.default_fixed32_mut().or_default(); + assert_that!(msg.default_fixed32(), eq(47)); + assert_that!(msg.default_fixed32_mut().get(), eq(47)); + assert_that!(msg.default_fixed32_mut().is_set(), eq(true)); + assert_that!(msg.default_fixed32_opt(), eq(Optional::Set(47))); +} + #[test] fn test_optional_fixed64_accessors() { let mut msg = TestAllTypes::new(); @@ -65,6 +93,33 @@ fn test_optional_fixed64_accessors() { assert_that!(msg.optional_fixed64(), eq(0)); } +#[test] +fn test_default_fixed64_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_fixed64(), eq(48)); + assert_that!(msg.default_fixed64_mut().get(), eq(48)); + assert_that!(msg.default_fixed64_mut().is_set(), eq(false)); + assert_that!(msg.default_fixed64_opt(), eq(Optional::Unset(48))); + + msg.default_fixed64_mut().set(999); + assert_that!(msg.default_fixed64(), eq(999)); + assert_that!(msg.default_fixed64_mut().get(), eq(999)); + assert_that!(msg.default_fixed64_mut().is_set(), eq(true)); + assert_that!(msg.default_fixed64_opt(), eq(Optional::Set(999))); + + msg.default_fixed64_mut().clear(); + assert_that!(msg.default_fixed64(), eq(48)); + assert_that!(msg.default_fixed64_mut().get(), eq(48)); + assert_that!(msg.default_fixed64_mut().is_set(), eq(false)); + assert_that!(msg.default_fixed64_opt(), eq(Optional::Unset(48))); + + msg.default_fixed64_mut().or_default(); + assert_that!(msg.default_fixed64(), eq(48)); + assert_that!(msg.default_fixed64_mut().get(), eq(48)); + assert_that!(msg.default_fixed64_mut().is_set(), eq(true)); + assert_that!(msg.default_fixed64_opt(), eq(Optional::Set(48))); +} + #[test] fn test_optional_int32_accessors() { let mut msg = TestAllTypes::new(); @@ -80,6 +135,33 @@ fn test_optional_int32_accessors() { assert_that!(msg.optional_int32(), eq(0)); } +#[test] +fn test_default_int32_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_int32(), eq(41)); + assert_that!(msg.default_int32_mut().get(), eq(41)); + assert_that!(msg.default_int32_mut().is_set(), eq(false)); + assert_that!(msg.default_int32_opt(), eq(Optional::Unset(41))); + + msg.default_int32_mut().set(999); + assert_that!(msg.default_int32(), eq(999)); + assert_that!(msg.default_int32_mut().get(), eq(999)); + assert_that!(msg.default_int32_mut().is_set(), eq(true)); + assert_that!(msg.default_int32_opt(), eq(Optional::Set(999))); + + msg.default_int32_mut().clear(); + assert_that!(msg.default_int32(), eq(41)); + assert_that!(msg.default_int32_mut().get(), eq(41)); + assert_that!(msg.default_int32_mut().is_set(), eq(false)); + assert_that!(msg.default_int32_opt(), eq(Optional::Unset(41))); + + msg.default_int32_mut().or_default(); + assert_that!(msg.default_int32(), eq(41)); + assert_that!(msg.default_int32_mut().get(), eq(41)); + assert_that!(msg.default_int32_mut().is_set(), eq(true)); + assert_that!(msg.default_int32_opt(), eq(Optional::Set(41))); +} + #[test] fn test_optional_int64_accessors() { let mut msg = TestAllTypes::new(); @@ -95,6 +177,33 @@ fn test_optional_int64_accessors() { assert_that!(msg.optional_int64(), eq(0)); } +#[test] +fn test_default_int64_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_int64(), eq(42)); + assert_that!(msg.default_int64_mut().get(), eq(42)); + assert_that!(msg.default_int64_mut().is_set(), eq(false)); + assert_that!(msg.default_int64_opt(), eq(Optional::Unset(42))); + + msg.default_int64_mut().set(999); + assert_that!(msg.default_int64(), eq(999)); + assert_that!(msg.default_int64_mut().get(), eq(999)); + assert_that!(msg.default_int64_mut().is_set(), eq(true)); + assert_that!(msg.default_int64_opt(), eq(Optional::Set(999))); + + msg.default_int64_mut().clear(); + assert_that!(msg.default_int64(), eq(42)); + assert_that!(msg.default_int64_mut().get(), eq(42)); + assert_that!(msg.default_int64_mut().is_set(), eq(false)); + assert_that!(msg.default_int64_opt(), eq(Optional::Unset(42))); + + msg.default_int64_mut().or_default(); + assert_that!(msg.default_int64(), eq(42)); + assert_that!(msg.default_int64_mut().get(), eq(42)); + assert_that!(msg.default_int64_mut().is_set(), eq(true)); + assert_that!(msg.default_int64_opt(), eq(Optional::Set(42))); +} + #[test] fn test_optional_sint32_accessors() { let mut msg = TestAllTypes::new(); @@ -110,6 +219,33 @@ fn test_optional_sint32_accessors() { assert_that!(msg.optional_sint32(), eq(0)); } +#[test] +fn test_default_sint32_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_sint32(), eq(-45)); + assert_that!(msg.default_sint32_mut().get(), eq(-45)); + assert_that!(msg.default_sint32_mut().is_set(), eq(false)); + assert_that!(msg.default_sint32_opt(), eq(Optional::Unset(-45))); + + msg.default_sint32_mut().set(999); + assert_that!(msg.default_sint32(), eq(999)); + assert_that!(msg.default_sint32_mut().get(), eq(999)); + assert_that!(msg.default_sint32_mut().is_set(), eq(true)); + assert_that!(msg.default_sint32_opt(), eq(Optional::Set(999))); + + msg.default_sint32_mut().clear(); + assert_that!(msg.default_sint32(), eq(-45)); + assert_that!(msg.default_sint32_mut().get(), eq(-45)); + assert_that!(msg.default_sint32_mut().is_set(), eq(false)); + assert_that!(msg.default_sint32_opt(), eq(Optional::Unset(-45))); + + msg.default_sint32_mut().or_default(); + assert_that!(msg.default_sint32(), eq(-45)); + assert_that!(msg.default_sint32_mut().get(), eq(-45)); + assert_that!(msg.default_sint32_mut().is_set(), eq(true)); + assert_that!(msg.default_sint32_opt(), eq(Optional::Set(-45))); +} + #[test] fn test_optional_sint64_accessors() { let mut msg = TestAllTypes::new(); @@ -125,6 +261,33 @@ fn test_optional_sint64_accessors() { assert_that!(msg.optional_sint64(), eq(0)); } +#[test] +fn test_default_sint64_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_sint64(), eq(46)); + assert_that!(msg.default_sint64_mut().get(), eq(46)); + assert_that!(msg.default_sint64_mut().is_set(), eq(false)); + assert_that!(msg.default_sint64_opt(), eq(Optional::Unset(46))); + + msg.default_sint64_mut().set(999); + assert_that!(msg.default_sint64(), eq(999)); + assert_that!(msg.default_sint64_mut().get(), eq(999)); + assert_that!(msg.default_sint64_mut().is_set(), eq(true)); + assert_that!(msg.default_sint64_opt(), eq(Optional::Set(999))); + + msg.default_sint64_mut().clear(); + assert_that!(msg.default_sint64(), eq(46)); + assert_that!(msg.default_sint64_mut().get(), eq(46)); + assert_that!(msg.default_sint64_mut().is_set(), eq(false)); + assert_that!(msg.default_sint64_opt(), eq(Optional::Unset(46))); + + msg.default_sint64_mut().or_default(); + assert_that!(msg.default_sint64(), eq(46)); + assert_that!(msg.default_sint64_mut().get(), eq(46)); + assert_that!(msg.default_sint64_mut().is_set(), eq(true)); + assert_that!(msg.default_sint64_opt(), eq(Optional::Set(46))); +} + #[test] fn test_optional_uint32_accessors() { let mut msg = TestAllTypes::new(); @@ -140,6 +303,33 @@ fn test_optional_uint32_accessors() { assert_that!(msg.optional_uint32(), eq(0)); } +#[test] +fn test_default_uint32_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_uint32(), eq(43)); + assert_that!(msg.default_uint32_mut().get(), eq(43)); + assert_that!(msg.default_uint32_mut().is_set(), eq(false)); + assert_that!(msg.default_uint32_opt(), eq(Optional::Unset(43))); + + msg.default_uint32_mut().set(999); + assert_that!(msg.default_uint32(), eq(999)); + assert_that!(msg.default_uint32_mut().get(), eq(999)); + assert_that!(msg.default_uint32_mut().is_set(), eq(true)); + assert_that!(msg.default_uint32_opt(), eq(Optional::Set(999))); + + msg.default_uint32_mut().clear(); + assert_that!(msg.default_uint32(), eq(43)); + assert_that!(msg.default_uint32_mut().get(), eq(43)); + assert_that!(msg.default_uint32_mut().is_set(), eq(false)); + assert_that!(msg.default_uint32_opt(), eq(Optional::Unset(43))); + + msg.default_uint32_mut().or_default(); + assert_that!(msg.default_uint32(), eq(43)); + assert_that!(msg.default_uint32_mut().get(), eq(43)); + assert_that!(msg.default_uint32_mut().is_set(), eq(true)); + assert_that!(msg.default_uint32_opt(), eq(Optional::Set(43))); +} + #[test] fn test_optional_uint64_accessors() { let mut msg = TestAllTypes::new(); @@ -155,6 +345,33 @@ fn test_optional_uint64_accessors() { assert_that!(msg.optional_uint64(), eq(0)); } +#[test] +fn test_default_uint64_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_uint64(), eq(44)); + assert_that!(msg.default_uint64_mut().get(), eq(44)); + assert_that!(msg.default_uint64_mut().is_set(), eq(false)); + assert_that!(msg.default_uint64_opt(), eq(Optional::Unset(44))); + + msg.default_uint64_mut().set(999); + assert_that!(msg.default_uint64(), eq(999)); + assert_that!(msg.default_uint64_mut().get(), eq(999)); + assert_that!(msg.default_uint64_mut().is_set(), eq(true)); + assert_that!(msg.default_uint64_opt(), eq(Optional::Set(999))); + + msg.default_uint64_mut().clear(); + assert_that!(msg.default_uint64(), eq(44)); + assert_that!(msg.default_uint64_mut().get(), eq(44)); + assert_that!(msg.default_uint64_mut().is_set(), eq(false)); + assert_that!(msg.default_uint64_opt(), eq(Optional::Unset(44))); + + msg.default_uint64_mut().or_default(); + assert_that!(msg.default_uint64(), eq(44)); + assert_that!(msg.default_uint64_mut().get(), eq(44)); + assert_that!(msg.default_uint64_mut().is_set(), eq(true)); + assert_that!(msg.default_uint64_opt(), eq(Optional::Set(44))); +} + #[test] fn test_optional_float_accessors() { let mut msg = TestAllTypes::new(); @@ -170,6 +387,33 @@ fn test_optional_float_accessors() { assert_that!(msg.optional_float(), eq(0.0)); } +#[test] +fn test_default_float_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_float(), eq(51.5)); + assert_that!(msg.default_float_mut().get(), eq(51.5)); + assert_that!(msg.default_float_mut().is_set(), eq(false)); + assert_that!(msg.default_float_opt(), eq(Optional::Unset(51.5))); + + msg.default_float_mut().set(999.9); + assert_that!(msg.default_float(), eq(999.9)); + assert_that!(msg.default_float_mut().get(), eq(999.9)); + assert_that!(msg.default_float_mut().is_set(), eq(true)); + assert_that!(msg.default_float_opt(), eq(Optional::Set(999.9))); + + msg.default_float_mut().clear(); + assert_that!(msg.default_float(), eq(51.5)); + assert_that!(msg.default_float_mut().get(), eq(51.5)); + assert_that!(msg.default_float_mut().is_set(), eq(false)); + assert_that!(msg.default_float_opt(), eq(Optional::Unset(51.5))); + + msg.default_float_mut().or_default(); + assert_that!(msg.default_float(), eq(51.5)); + assert_that!(msg.default_float_mut().get(), eq(51.5)); + assert_that!(msg.default_float_mut().is_set(), eq(true)); + assert_that!(msg.default_float_opt(), eq(Optional::Set(51.5))); +} + #[test] fn test_optional_double_accessors() { let mut msg = TestAllTypes::new(); @@ -185,6 +429,33 @@ fn test_optional_double_accessors() { assert_that!(msg.optional_double(), eq(0.0)); } +#[test] +fn test_default_double_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_double(), eq(52e3)); + assert_that!(msg.default_double_mut().get(), eq(52e3)); + assert_that!(msg.default_double_mut().is_set(), eq(false)); + assert_that!(msg.default_double_opt(), eq(Optional::Unset(52e3))); + + msg.default_double_mut().set(999.9); + assert_that!(msg.default_double(), eq(999.9)); + assert_that!(msg.default_double_mut().get(), eq(999.9)); + assert_that!(msg.default_double_mut().is_set(), eq(true)); + assert_that!(msg.default_double_opt(), eq(Optional::Set(999.9))); + + msg.default_double_mut().clear(); + assert_that!(msg.default_double(), eq(52e3)); + assert_that!(msg.default_double_mut().get(), eq(52e3)); + assert_that!(msg.default_double_mut().is_set(), eq(false)); + assert_that!(msg.default_double_opt(), eq(Optional::Unset(52e3))); + + msg.default_double_mut().or_default(); + assert_that!(msg.default_double(), eq(52e3)); + assert_that!(msg.default_double_mut().get(), eq(52e3)); + assert_that!(msg.default_double_mut().is_set(), eq(true)); + assert_that!(msg.default_double_opt(), eq(Optional::Set(52e3))); +} + #[test] fn test_optional_bool_accessors() { let mut msg = TestAllTypes::new(); @@ -197,6 +468,33 @@ fn test_optional_bool_accessors() { assert_that!(msg.optional_bool_opt(), eq(Optional::Unset(false))); } +#[test] +fn test_default_bool_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.default_bool(), eq(true)); + assert_that!(msg.default_bool_mut().get(), eq(true)); + assert_that!(msg.default_bool_mut().is_set(), eq(false)); + assert_that!(msg.default_bool_opt(), eq(Optional::Unset(true))); + + msg.default_bool_mut().set(false); + assert_that!(msg.default_bool(), eq(false)); + assert_that!(msg.default_bool_mut().get(), eq(false)); + assert_that!(msg.default_bool_mut().is_set(), eq(true)); + assert_that!(msg.default_bool_opt(), eq(Optional::Set(false))); + + msg.default_bool_mut().clear(); + assert_that!(msg.default_bool(), eq(true)); + assert_that!(msg.default_bool_mut().get(), eq(true)); + assert_that!(msg.default_bool_mut().is_set(), eq(false)); + assert_that!(msg.default_bool_opt(), eq(Optional::Unset(true))); + + msg.default_bool_mut().or_default(); + assert_that!(msg.default_bool(), eq(true)); + assert_that!(msg.default_bool_mut().get(), eq(true)); + assert_that!(msg.default_bool_mut().is_set(), eq(true)); + assert_that!(msg.default_bool_opt(), eq(Optional::Set(true))); +} + #[test] fn test_optional_bytes_accessors() { let mut msg = TestAllTypes::new(); @@ -392,9 +690,125 @@ fn test_oneof_accessors() { assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); msg.oneof_uint32_set(Some(7)); - msg.oneof_bytes_mut().set(b""); + msg.oneof_bytes_mut().set(b"123"); assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0))); - // This should show it set to the OneofBytes but its not supported yet. - assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); + assert_that!(msg.oneof_field(), matches_pattern!(OneofBytes(eq(b"123")))); +} + +macro_rules! generate_repeated_numeric_test { + ($(($t: ty, $field: ident)),*) => { + paste! { $( + #[test] + fn [< test_repeated_ $field _accessors >]() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.[< repeated_ $field >]().len(), eq(0)); + assert_that!(msg.[]().get(0), none()); + + let mut mutator = msg.[](); + mutator.push(1 as $t); + assert_that!(mutator.len(), eq(1)); + assert_that!(mutator.get(0), some(eq(1 as $t))); + mutator.set(0, 2 as $t); + assert_that!(mutator.get(0), some(eq(2 as $t))); + mutator.push(1 as $t); + + mutator.push(3 as $t); + assert_that!(mutator.get_mut(2).is_some(), eq(true)); + let mut mut_elem = mutator.get_mut(2).unwrap(); + mut_elem.set(4 as $t); + assert_that!(mut_elem.get(), eq(4 as $t)); + mut_elem.clear(); + assert_that!(mut_elem.get(), eq(0 as $t)); + + assert_that!( + mutator.iter().collect::>(), + eq(vec![2 as $t, 1 as $t, 0 as $t]) + ); + assert_that!( + (*mutator).into_iter().collect::>(), + eq(vec![2 as $t, 1 as $t, 0 as $t]) + ); + + for mut mutable_elem in msg.[]() { + mutable_elem.set(0 as $t); + } + assert_that!( + msg.[]().iter().all(|v| v == (0 as $t)), + eq(true) + ); + } + + #[test] + fn [< test_repeated_ $field _set >]() { + let mut msg = TestAllTypes::new(); + let mut mutator = msg.[](); + let mut msg2 = TestAllTypes::new(); + let mut mutator2 = msg2.[](); + for i in 0..5 { + mutator2.push(i as $t); + } + protobuf::MutProxy::set(&mut mutator, *mutator2); + + assert_that!( + mutator.iter().collect::>(), + eq(mutator2.iter().collect::>()) + ); + } + )* } + }; +} + +generate_repeated_numeric_test!( + (i32, int32), + (u32, uint32), + (i64, int64), + (u64, uint64), + (f32, float), + (f64, double) +); + +#[test] +fn test_repeated_bool_accessors() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.repeated_bool().len(), eq(0)); + assert_that!(msg.repeated_bool().get(0), none()); + + let mut mutator = msg.repeated_bool_mut(); + mutator.push(true); + assert_that!(mutator.len(), eq(1)); + assert_that!(mutator.get(0), some(eq(true))); + mutator.set(0, false); + assert_that!(mutator.get(0), some(eq(false))); + mutator.push(true); + + mutator.push(false); + assert_that!(mutator.get_mut(2), pat!(Some(_))); + let mut mut_elem = mutator.get_mut(2).unwrap(); + mut_elem.set(true); + assert_that!(mut_elem.get(), eq(true)); + mut_elem.clear(); + assert_that!(mut_elem.get(), eq(false)); + + assert_that!(mutator.iter().collect::>(), eq(vec![false, true, false])); + assert_that!((*mutator).into_iter().collect::>(), eq(vec![false, true, false])); + + for mut mutable_elem in msg.repeated_bool_mut() { + mutable_elem.set(false); + } + assert_that!(msg.repeated_bool().iter().all(|v| v), eq(false)); +} + +#[test] +fn test_repeated_bool_set() { + let mut msg = TestAllTypes::new(); + let mut mutator = msg.repeated_bool_mut(); + let mut msg2 = TestAllTypes::new(); + let mut mutator2 = msg2.repeated_bool_mut(); + for _ in 0..5 { + mutator2.push(true); + } + protobuf::MutProxy::set(&mut mutator, *mutator2); + + assert_that!(mutator.iter().collect::>(), eq(mutator2.iter().collect::>())); } diff --git a/rust/upb.rs b/rust/upb.rs index cd5cc77e74..b6fd7b322a 100644 --- a/rust/upb.rs +++ b/rust/upb.rs @@ -7,7 +7,7 @@ //! UPB FFI wrapper code for use by Rust Protobuf. -use crate::__internal::{Private, RawArena, RawMessage}; +use crate::__internal::{Private, PtrAndLen, RawArena, RawMessage, RawRepeatedField}; use std::alloc; use std::alloc::Layout; use std::cell::UnsafeCell; @@ -150,7 +150,7 @@ const UPB_SCRATCH_SPACE_BYTES: usize = 64_000; /// with readonly access. pub struct ScratchSpace; impl ScratchSpace { - pub fn zeroed_block() -> RawMessage { + pub fn zeroed_block(_private: Private) -> RawMessage { unsafe { INIT.call_once(|| { let layout = @@ -284,6 +284,173 @@ pub fn copy_bytes_in_arena_if_needed_by_runtime<'a>( } } +/// RepeatedFieldInner contains a `upb_Array*` as well as a reference to an +/// `Arena`, most likely that of the containing `Message`. upb requires an Arena +/// to perform mutations on a repeated field. +#[derive(Clone, Copy, Debug)] +pub struct RepeatedFieldInner<'msg> { + pub raw: RawRepeatedField, + pub arena: &'msg Arena, +} + +#[derive(Debug)] +pub struct RepeatedField<'msg, T: ?Sized> { + inner: RepeatedFieldInner<'msg>, + _phantom: PhantomData<&'msg mut T>, +} + +// These use manual impls instead of derives to avoid unnecessary bounds on `T`. +// This problem is referred to as "perfect derive". +// https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/ +impl<'msg, T: ?Sized> Copy for RepeatedField<'msg, T> {} +impl<'msg, T: ?Sized> Clone for RepeatedField<'msg, T> { + fn clone(&self) -> RepeatedField<'msg, T> { + *self + } +} + +impl<'msg, T: ?Sized> RepeatedField<'msg, T> { + pub fn len(&self) -> usize { + unsafe { upb_Array_Size(self.inner.raw) } + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn from_inner(_private: Private, inner: RepeatedFieldInner<'msg>) -> Self { + Self { inner, _phantom: PhantomData } + } +} + +// Transcribed from google3/third_party/upb/upb/message/value.h +#[repr(C)] +#[derive(Clone, Copy)] +union upb_MessageValue { + bool_val: bool, + float_val: std::ffi::c_float, + double_val: std::ffi::c_double, + uint32_val: u32, + int32_val: i32, + uint64_val: u64, + int64_val: i64, + array_val: *const std::ffi::c_void, + map_val: *const std::ffi::c_void, + msg_val: *const std::ffi::c_void, + str_val: PtrAndLen, +} + +// Transcribed from google3/third_party/upb/upb/base/descriptor_constants.h +#[repr(C)] +#[allow(dead_code)] +enum UpbCType { + Bool = 1, + Float = 2, + Int32 = 3, + UInt32 = 4, + Enum = 5, + Message = 6, + Double = 7, + Int64 = 8, + UInt64 = 9, + String = 10, + Bytes = 11, +} + +extern "C" { + #[allow(dead_code)] + fn upb_Array_New(a: RawArena, r#type: std::ffi::c_int) -> RawRepeatedField; + fn upb_Array_Size(arr: RawRepeatedField) -> usize; + fn upb_Array_Set(arr: RawRepeatedField, i: usize, val: upb_MessageValue); + fn upb_Array_Get(arr: RawRepeatedField, i: usize) -> upb_MessageValue; + fn upb_Array_Append(arr: RawRepeatedField, val: upb_MessageValue, arena: RawArena); + fn upb_Array_Resize(arr: RawRepeatedField, size: usize, arena: RawArena); +} + +macro_rules! impl_repeated_primitives { + ($(($rs_type:ty, $union_field:ident, $upb_tag:expr)),*) => { + $( + impl<'msg> RepeatedField<'msg, $rs_type> { + #[allow(dead_code)] + fn new(arena: &'msg Arena) -> Self { + Self { + inner: RepeatedFieldInner { + raw: unsafe { upb_Array_New(arena.raw, $upb_tag as std::ffi::c_int) }, + arena, + }, + _phantom: PhantomData, + } + } + pub fn push(&mut self, val: $rs_type) { + unsafe { upb_Array_Append( + self.inner.raw, + upb_MessageValue { $union_field: val }, + self.inner.arena.raw(), + ) } + } + pub fn get(&self, i: usize) -> Option<$rs_type> { + if i >= self.len() { + None + } else { + unsafe { Some(upb_Array_Get(self.inner.raw, i).$union_field) } + } + } + pub fn set(&self, i: usize, val: $rs_type) { + if i >= self.len() { + return; + } + unsafe { upb_Array_Set( + self.inner.raw, + i, + upb_MessageValue { $union_field: val }, + ) } + } + pub fn copy_from(&mut self, src: &RepeatedField<'_, $rs_type>) { + // TODO: Optimize this copy_from implementation using memcopy. + // NOTE: `src` cannot be `self` because this would violate borrowing rules. + unsafe { upb_Array_Resize(self.inner.raw, 0, self.inner.arena.raw()) }; + // `upb_Array_DeepClone` is not used here because it returns + // a new `upb_Array*`. The contained `RawRepeatedField` must + // then be set to this new pointer, but other copies of this + // pointer may exist because of re-borrowed `RepeatedMut`s. + // Alternatively, a `clone_into` method could be exposed by upb. + for i in 0..src.len() { + self.push(src.get(i).unwrap()); + } + } + } + )* + } +} + +impl_repeated_primitives!( + (bool, bool_val, UpbCType::Bool), + (f32, float_val, UpbCType::Float), + (f64, double_val, UpbCType::Double), + (i32, int32_val, UpbCType::Int32), + (u32, uint32_val, UpbCType::UInt32), + (i64, int64_val, UpbCType::Int64), + (u64, uint64_val, UpbCType::UInt64) +); + +/// Returns a static thread-local empty RepeatedFieldInner for use in a +/// RepeatedView. +/// +/// # Safety +/// TODO: Split RepeatedFieldInner into mut and const variants to +/// enforce safety. The returned array must never be mutated. +pub unsafe fn empty_array() -> RepeatedFieldInner<'static> { + // TODO: Consider creating empty array in C. + fn new_repeated_field_inner() -> RepeatedFieldInner<'static> { + let arena = Box::leak::<'static>(Box::new(Arena::new())); + // Provide `i32` as a placeholder type. + RepeatedField::<'static, i32>::new(arena).inner + } + thread_local! { + static REPEATED_FIELD: RepeatedFieldInner<'static> = new_repeated_field_inner(); + } + + REPEATED_FIELD.with(|inner| *inner) +} + #[cfg(test)] mod tests { use super::*; @@ -309,4 +476,35 @@ mod tests { }; assert_eq!(&*serialized_data, b"Hello world"); } + + #[test] + fn i32_array() { + let arena = Arena::new(); + let mut arr = RepeatedField::::new(&arena); + assert_eq!(arr.len(), 0); + arr.push(1); + assert_eq!(arr.get(0), Some(1)); + assert_eq!(arr.len(), 1); + arr.set(0, 3); + assert_eq!(arr.get(0), Some(3)); + for i in 0..2048 { + arr.push(i); + assert_eq!(arr.get(arr.len() - 1), Some(i)); + } + } + #[test] + fn u32_array() { + let mut arena = Arena::new(); + let mut arr = RepeatedField::::new(&mut arena); + assert_eq!(arr.len(), 0); + arr.push(1); + assert_eq!(arr.get(0), Some(1)); + assert_eq!(arr.len(), 1); + arr.set(0, 3); + assert_eq!(arr.get(0), Some(3)); + for i in 0..2048 { + arr.push(i); + assert_eq!(arr.get(arr.len() - 1), Some(i)); + } + } } diff --git a/rust/upb_kernel/BUILD b/rust/upb_kernel/BUILD index dc65231433..b06f182117 100644 --- a/rust/upb_kernel/BUILD +++ b/rust/upb_kernel/BUILD @@ -8,6 +8,7 @@ cc_library( "//rust:__subpackages__", ], deps = [ + "//upb:collections", "//upb:mem", ], ) diff --git a/rust/upb_kernel/upb_api.c b/rust/upb_kernel/upb_api.c index 985749da23..a30b4dd9bb 100644 --- a/rust/upb_kernel/upb_api.c +++ b/rust/upb_kernel/upb_api.c @@ -8,4 +8,5 @@ #define UPB_BUILD_API -#include "upb/mem/arena.h" // IWYU pragma: keep +#include "upb/collections/array.h" // IWYU pragma: keep +#include "upb/mem/arena.h" // IWYU pragma: keep diff --git a/rust/utf8.rs b/rust/utf8.rs index 05f4c499e3..56a1c20b93 100644 --- a/rust/utf8.rs +++ b/rust/utf8.rs @@ -241,7 +241,7 @@ impl<'a> Iterator for Utf8Chunks<'a> { /// # Safety /// `index` must be in-bounds for `x` unsafe fn split_at_unchecked(x: &[u8], index: usize) -> (&[u8], &[u8]) { - // SAFTEY: in-bounds as promised by the caller + // SAFETY: in-bounds as promised by the caller unsafe { (x.get_unchecked(..index), x.get_unchecked(index..)) } } diff --git a/rust/vtable.rs b/rust/vtable.rs index 6d6e4e96ba..2327e56b69 100644 --- a/rust/vtable.rs +++ b/rust/vtable.rs @@ -258,6 +258,15 @@ pub struct PrimitiveVTable { pub(crate) getter: unsafe extern "C" fn(msg: RawMessage) -> T, } +#[doc(hidden)] +#[derive(Debug)] +/// A generic thunk vtable for mutating an `optional` primitive field. +pub struct PrimitiveOptionalMutVTable { + pub(crate) base: PrimitiveVTable, + pub(crate) clearer: unsafe extern "C" fn(msg: RawMessage), + pub(crate) default: T, +} + impl PrimitiveVTable { #[doc(hidden)] pub const fn new( @@ -269,6 +278,19 @@ impl PrimitiveVTable { } } +impl PrimitiveOptionalMutVTable { + #[doc(hidden)] + pub const fn new( + _private: Private, + getter: unsafe extern "C" fn(msg: RawMessage) -> T, + setter: unsafe extern "C" fn(msg: RawMessage, val: T), + clearer: unsafe extern "C" fn(msg: RawMessage), + default: T, + ) -> Self { + Self { base: PrimitiveVTable { getter, setter }, clearer, default } + } +} + macro_rules! impl_raw_vtable_mutator_get_set { ($($t:ty),*) => { $( @@ -398,3 +420,36 @@ impl<'msg> RawVTableOptionalMutatorData<'msg, [u8]> { self } } + +macro_rules! impl_raw_vtable_optional_mutator_data { + ($($t:ty),*) => { + $( + impl<'msg> RawVTableOptionalMutatorData<'msg, $t> { + pub(crate) fn set_absent_to_default(self) -> Self { + // SAFETY: + // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as + // promised by the caller of `new`. + self.set(self.vtable.default) + } + + pub(crate) fn set(self, val: $t) -> Self { + // SAFETY: + // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as + // promised by the caller of `new`. + unsafe { (self.vtable.base.setter)(self.msg_ref.msg(), val.into()) } + self + } + + pub(crate) fn clear(self) -> Self { + // SAFETY: + // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as + // promised by the caller of `new`. + unsafe { (self.vtable.clearer)(self.msg_ref.msg()) } + self + } + } + )* + } +} + +impl_raw_vtable_optional_mutator_data!(bool, f32, f64, i32, i64, u32, u64); diff --git a/src/BUILD.bazel b/src/BUILD.bazel index 2ce3449845..7c42d0b01a 100644 --- a/src/BUILD.bazel +++ b/src/BUILD.bazel @@ -38,6 +38,7 @@ pkg_filegroup( conformance_test( name = "conformance_test", failure_list = "//conformance:failure_list_cpp.txt", + maximum_edition = "2023", testee = "//conformance:conformance_cpp", text_format_failure_list = "//conformance:text_format_failure_list_cpp.txt", ) diff --git a/src/file_lists.cmake b/src/file_lists.cmake index d320be43a6..e4718cf8a3 100644 --- a/src/file_lists.cmake +++ b/src/file_lists.cmake @@ -289,7 +289,6 @@ set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/allowlists/empty_package.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/allowlists/open_enum.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/allowlists/unused_imports.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/allowlists/weak_imports.cc ${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 @@ -384,6 +383,7 @@ set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/retention.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/accessors.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/repeated_scalar.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/singular_message.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/singular_string.cc diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index 8961ca6af1..3bb21ad0ab 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -162,6 +162,7 @@ cc_library( copts = COPTS, includes = ["wkt"], linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = ["//pkg:__pkg__"], deps = [":protobuf_nowkt"], ) @@ -198,7 +199,7 @@ cc_library( "port_def.inc", "port_undef.inc", ], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -212,7 +213,7 @@ cc_library( name = "varint_shuffle", hdrs = ["varint_shuffle.h"], copts = COPTS, - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -248,7 +249,7 @@ cc_library( name = "arena_align", srcs = ["arena_align.cc"], hdrs = ["arena_align.h"], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -264,7 +265,7 @@ cc_library( cc_library( name = "arena_cleanup", hdrs = ["arena_cleanup.h"], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -278,7 +279,7 @@ cc_library( cc_library( name = "arena_allocation_policy", hdrs = ["arena_allocation_policy.h"], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -291,7 +292,7 @@ cc_library( cc_library( name = "string_block", hdrs = ["string_block.h"], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", deps = [ ":arena_align", "@com_google_absl//absl/base:core_headers", @@ -320,7 +321,7 @@ cc_library( "serial_arena.h", "thread_safe_arena.h", ], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -343,7 +344,7 @@ cc_library( name = "internal_visibility", hdrs = ["internal_visibility.h"], copts = COPTS, - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -355,7 +356,7 @@ cc_library( testonly = 1, hdrs = ["internal_visibility_for_testing.h"], copts = COPTS, - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -388,6 +389,7 @@ cc_library( "arena.h", "arenastring.h", "arenaz_sampler.h", + "descriptor_lite.h", "endian.h", "explicitly_constructed.h", "extension_set.h", @@ -419,8 +421,8 @@ cc_library( "-Wno-error", ], }), - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = [ "//:__pkg__", "//pkg:__pkg__", @@ -506,8 +508,8 @@ cc_library( "wire_format.h", ], copts = COPTS, - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = [ "//:__pkg__", "//pkg:__pkg__", @@ -549,8 +551,8 @@ cc_test( cc_library( name = "protobuf", copts = COPTS, - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = [ "//:__pkg__", "//pkg:__pkg__", @@ -573,14 +575,15 @@ cc_library( "**/*.h", "**/*.inc", ]), + strip_include_prefix = "/src", ) cc_library( name = "descriptor_legacy", hdrs = ["descriptor_legacy.h"], copts = COPTS, - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = ["//:__subpackages__"], deps = [ ":port_def", @@ -593,8 +596,8 @@ cc_library( name = "descriptor_visitor", hdrs = ["descriptor_visitor.h"], copts = COPTS, - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = ["//:__subpackages__"], deps = [ ":port_def", @@ -749,6 +752,22 @@ proto_library( ], ) +proto_library( + name = "unittest_features_proto", + srcs = ["unittest_features.proto"], + strip_import_prefix = "/src", + visibility = ["//src/google/protobuf:__subpackages__"], + deps = [ + ":descriptor_proto", + ], +) + +cc_proto_library( + name = "unittest_features_cc_proto", + visibility = ["//src/google/protobuf:__subpackages__"], + deps = [":unittest_features_proto"], +) + proto_library( name = "generic_test_protos", srcs = [":test_proto_srcs"], diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 930ad77df0..429b41c6f8 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -58,29 +58,31 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _impl_.type_url_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _impl_.value_), +const ::uint32_t + TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _impl_.type_url_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _impl_.value_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, -1, -1, sizeof(::google::protobuf::Any)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Any_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\031google/protobuf/any.proto\022\017google.prot" "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002" " \001(\014Bv\n\023com.google.protobufB\010AnyProtoP\001Z" @@ -193,6 +195,16 @@ inline void Any::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Any::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Any::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Any::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Any) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -304,13 +316,6 @@ const ::_pbi::TcParseTable<1, 2, 0, 36, 2> Any::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Any::_class_data_ = { - Any::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Any::GetClassData() const { - return &_class_data_; -} void Any::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index 13968ac3a8..71713fbe8f 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -203,7 +203,7 @@ class PROTOBUF_EXPORT Any final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -226,11 +226,9 @@ class PROTOBUF_EXPORT Any final : protected: explicit Any(::google::protobuf::Arena* arena); Any(::google::protobuf::Arena* arena, const Any& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 8823fd6e88..773786a15b 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -113,59 +113,60 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fapi_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.methods_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.version_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.source_context_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.mixins_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.syntax_), - ~0u, - ~0u, - ~0u, - ~0u, - 0, - ~0u, - ~0u, - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.request_type_url_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.request_streaming_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.response_type_url_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.response_streaming_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.syntax_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _impl_.root_), +const ::uint32_t + TableStruct_google_2fprotobuf_2fapi_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.methods_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.version_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.source_context_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.mixins_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Api, _impl_.syntax_), + ~0u, + ~0u, + ~0u, + ~0u, + 0, + ~0u, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.request_type_url_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.request_streaming_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.response_type_url_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.response_streaming_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_.syntax_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _impl_.root_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, 15, -1, sizeof(::google::protobuf::Api)}, {22, -1, -1, sizeof(::google::protobuf::Method)}, {37, -1, -1, sizeof(::google::protobuf::Mixin)}, @@ -176,7 +177,8 @@ static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Method_default_instance_._instance, &::google::protobuf::_Mixin_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\031google/protobuf/api.proto\022\017google.prot" "obuf\032$google/protobuf/source_context.pro" "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014" @@ -330,6 +332,16 @@ inline void Api::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Api::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Api::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Api::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Api) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -558,13 +570,6 @@ const ::_pbi::TcParseTable<3, 7, 4, 39, 2> Api::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Api::_class_data_ = { - Api::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Api::GetClassData() const { - return &_class_data_; -} void Api::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -708,6 +713,16 @@ inline void Method::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Method::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Method::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Method::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Method) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -924,13 +939,6 @@ const ::_pbi::TcParseTable<3, 7, 1, 68, 2> Method::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Method::_class_data_ = { - Method::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Method::GetClassData() const { - return &_class_data_; -} void Method::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1051,6 +1059,16 @@ inline void Mixin::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Mixin::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Mixin::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Mixin::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1165,13 +1183,6 @@ const ::_pbi::TcParseTable<1, 2, 0, 38, 2> Mixin::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Mixin::_class_data_ = { - Mixin::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Mixin::GetClassData() const { - return &_class_data_; -} void Mixin::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index f55e3599f8..74bd6c5059 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -176,7 +176,7 @@ class PROTOBUF_EXPORT Mixin final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -199,11 +199,9 @@ class PROTOBUF_EXPORT Mixin final : protected: explicit Mixin(::google::protobuf::Arena* arena); Mixin(::google::protobuf::Arena* arena, const Mixin& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -375,7 +373,7 @@ class PROTOBUF_EXPORT Method final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -398,11 +396,9 @@ class PROTOBUF_EXPORT Method final : protected: explicit Method(::google::protobuf::Arena* arena); Method(::google::protobuf::Arena* arena, const Method& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -648,7 +644,7 @@ class PROTOBUF_EXPORT Api final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -671,11 +667,9 @@ class PROTOBUF_EXPORT Api final : protected: explicit Api(::google::protobuf::Arena* arena); Api(::google::protobuf::Arena* arena, const Api& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index ffc9cb1608..c4f8f5fc2c 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -261,7 +261,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // again. template PROTOBUF_ALWAYS_INLINE static void Destroy(T* obj) { - if (InternalGetOwningArena(obj) == nullptr) delete obj; + if (InternalGetArena(obj) == nullptr) delete obj; } // Allocates memory with the specific size and alignment. @@ -392,21 +392,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { struct Rank1 {}; struct Rank0 : Rank1 {}; - static Arena* GetOwningArena(const T* p) { - return GetOwningArena(Rank0{}, p); - } - - template - static auto GetOwningArena(Rank0, const U* p) - -> EnableIfArenaGetOwningArena())> { - return p->GetOwningArena(); - } - - template - static Arena* GetOwningArena(Rank1, const U*) { - return nullptr; - } - static void InternalSwap(T* a, T* b) { a->InternalSwap(b); } static Arena* GetArena(T* p) { return GetArena(Rank0{}, p); } @@ -458,28 +443,10 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { friend class TestUtil::ReflectionTester; }; - // Provides access to protected GetOwningArena to generated messages. For - // internal use only. - template - static Arena* InternalGetOwningArena(T* p) { - ABSL_DCHECK_EQ(InternalHelper::GetOwningArena(p), - InternalHelper::GetArena(p)); - return InternalHelper::GetOwningArena(p); - } - - // Wraps InternalGetArena() and will be removed soon. - // For internal use only. - template - static Arena* InternalGetArenaForAllocation(T* p) { - return InternalHelper::GetArena(p); - } - // Provides access to protected GetArena to generated messages. // For internal use only. template static Arena* InternalGetArena(T* p) { - ABSL_DCHECK_EQ(InternalHelper::GetOwningArena(p), - InternalHelper::GetArena(p)); return InternalHelper::GetArena(p); } diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 4a2d502cc1..21041129fb 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -561,16 +561,6 @@ TEST(ArenaTest, UnsafeArenaSwap) { TestUtil::ExpectAllFieldsSet(*message2); } -TEST(ArenaTest, GetOwningArena) { - Arena arena; - auto* m1 = Arena::CreateMessage(&arena); - EXPECT_EQ(Arena::InternalGetOwningArena(m1), &arena); - EXPECT_EQ(&arena, Arena::InternalGetOwningArena( - m1->mutable_repeated_foreign_message())); - EXPECT_EQ(&arena, - Arena::InternalGetOwningArena(m1->mutable_repeated_int32())); -} - TEST(ArenaTest, SwapBetweenArenasUsingReflection) { Arena arena1; TestAllTypes* arena1_message = Arena::CreateMessage(&arena1); diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h index dea2aecab7..dc9fe561c4 100644 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -337,7 +337,7 @@ struct PROTOBUF_EXPORT ArenaStringPtr { // Returns a pointer to the stored contents for this instance. // This method is for internal debugging and tracking purposes only. PROTOBUF_NDEBUG_INLINE const std::string* UnsafeGetPointer() const - PROTOBUF_RETURNS_NONNULL { + ABSL_ATTRIBUTE_RETURNS_NONNULL { return tagged_ptr_.Get(); } @@ -383,7 +383,7 @@ struct PROTOBUF_EXPORT ArenaStringPtr { // Generated code only! An optimization, in certain cases the generated // code is certain we can obtain a std::string with no default checks and // tag tests. - std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL; + std::string* UnsafeMutablePointer() ABSL_ATTRIBUTE_RETURNS_NONNULL; // Returns true if this instances holds an immutable default value. inline bool IsDefault() const { return tagged_ptr_.IsDefault(); } diff --git a/src/google/protobuf/arenaz_sampler_test.cc b/src/google/protobuf/arenaz_sampler_test.cc index c71162467a..20a0473207 100644 --- a/src/google/protobuf/arenaz_sampler_test.cc +++ b/src/google/protobuf/arenaz_sampler_test.cc @@ -401,6 +401,7 @@ TEST(ThreadSafeArenazSamplerTest, InitialBlockReportsZeroUsedAndWasted) { for (int i = 0; i < 10; ++i) { char block[kSize]; google::protobuf::Arena arena(/*initial_block=*/block, /*initial_block_size=*/kSize); + benchmark::DoNotOptimize(&arena); sampler.Iterate([&](const ThreadSafeArenaStats& h) { const auto& histbin = h.block_histogram[ThreadSafeArenaStats::FindBin(kSize)]; diff --git a/src/google/protobuf/compiler/BUILD.bazel b/src/google/protobuf/compiler/BUILD.bazel index 273dae00b4..f98c31785b 100644 --- a/src/google/protobuf/compiler/BUILD.bazel +++ b/src/google/protobuf/compiler/BUILD.bazel @@ -42,7 +42,7 @@ cc_library( "parser.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -66,7 +66,7 @@ cc_library( "scc.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -87,7 +87,7 @@ cc_library( "versions_suffix.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = [ "//src/google/protobuf/compiler:__subpackages__", ], @@ -107,7 +107,7 @@ cc_library( "zip_writer.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ ":code_generator", @@ -133,6 +133,7 @@ cc_library( "main.cc", ], copts = COPTS, + strip_include_prefix = "/src", visibility = [ "//:__pkg__", "//pkg:__pkg__", @@ -154,6 +155,23 @@ cc_library( ], ) +# This is a build of the protobuf compiler without code generators. +cc_binary( + name = "protoc_minimal", + srcs = [ + "main_no_generators.cc", + ], + copts = COPTS, + visibility = [ + "//src/google/protobuf:__subpackages__", + ], + deps = [ + ":command_line_interface", + "//src/google/protobuf:port_def", + "@com_google_absl//absl/log:initialize", + ], +) + # 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( @@ -397,7 +415,7 @@ cc_library( name = "retention", srcs = ["retention.cc"], hdrs = ["retention.h"], - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = ["//src/google/protobuf:__subpackages__"], deps = [ "//src/google/protobuf:protobuf_nowkt", diff --git a/src/google/protobuf/compiler/allowlists/BUILD.bazel b/src/google/protobuf/compiler/allowlists/BUILD.bazel index ebedfadf91..e6671c05c1 100644 --- a/src/google/protobuf/compiler/allowlists/BUILD.bazel +++ b/src/google/protobuf/compiler/allowlists/BUILD.bazel @@ -7,11 +7,12 @@ cc_library( name = "allowlist", hdrs = ["allowlist.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/allowlists", + strip_include_prefix = "/src", deps = [ "//src/google/protobuf/stubs", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base:core_headers", + "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", ], @@ -24,11 +25,10 @@ cc_library( "empty_package.cc", "open_enum.cc", "unused_imports.cc", - "weak_imports.cc", ], hdrs = ["allowlists.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/allowlists", + strip_include_prefix = "/src", visibility = ["//src/google/protobuf:__subpackages__"], deps = [ ":allowlist", diff --git a/src/google/protobuf/compiler/allowlists/allowlist.h b/src/google/protobuf/compiler/allowlists/allowlist.h index 7a7a97d88c..71034db07e 100644 --- a/src/google/protobuf/compiler/allowlists/allowlist.h +++ b/src/google/protobuf/compiler/allowlists/allowlist.h @@ -10,10 +10,12 @@ #include #include +#include #include #include "absl/algorithm/container.h" #include "google/protobuf/stubs/common.h" +#include "absl/container/flat_hash_set.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" @@ -29,8 +31,10 @@ enum AllowlistFlags : unsigned int { kNone = 0, kMatchPrefix = 1 << 1, kAllowAllInOss = 1 << 2, + kAllowAllWhenEmpty = 1 << 3, }; + #if !defined(__GNUC__) || defined(__clang__) || PROTOBUF_GNUC_MIN(9, 1) using maybe_string_view = absl::string_view; #else diff --git a/src/google/protobuf/compiler/allowlists/weak_imports.cc b/src/google/protobuf/compiler/allowlists/weak_imports.cc deleted file mode 100644 index 5fca2d6793..0000000000 --- a/src/google/protobuf/compiler/allowlists/weak_imports.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd - -#include "google/protobuf/compiler/allowlists/allowlists.h" - -#include "absl/strings/string_view.h" -#include "google/protobuf/compiler/allowlists/allowlist.h" - -namespace google { -namespace protobuf { -namespace compiler { - -// NOTE: Allowlists in this file are not accepting new entries unless otherwise -// specified. - -static constexpr auto kWeakImports = internal::MakeAllowlist({ -// Intentionally left blank. -}); - -bool IsWeakImportFile(absl::string_view file) { - return kWeakImports.Allows(file); -} -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 863192d735..332cf53dfb 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -23,6 +23,9 @@ #include "google/protobuf/descriptor.h" #include "google/protobuf/feature_resolver.h" +// Must be included last. +#include "google/protobuf/port_def.inc" + namespace google { namespace protobuf { namespace compiler { @@ -57,6 +60,14 @@ bool CodeGenerator::GenerateAll(const std::vector& files, absl::StatusOr CodeGenerator::BuildFeatureSetDefaults() const { + if ((GetSupportedFeatures() & FEATURE_SUPPORTS_EDITIONS) == 0) { + // For generators that don't fully support editions yet, provide an + // optimistic set of defaults. Protoc will check this condition later + // anyway. + return FeatureResolver::CompileDefaults( + FeatureSet::descriptor(), GetFeatureExtensions(), + PROTOBUF_MINIMUM_EDITION, PROTOBUF_MAXIMUM_EDITION); + } return FeatureResolver::CompileDefaults( FeatureSet::descriptor(), GetFeatureExtensions(), GetMinimumEdition(), GetMaximumEdition()); @@ -131,3 +142,5 @@ bool IsKnownFeatureProto(absl::string_view filename) { } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index b8bc3792d0..7ce2cfba72 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -135,9 +135,9 @@ class PROTOC_EXPORT CodeGenerator { protected: // Retrieves the resolved source features for a given descriptor. All the - // features that are imported (from the proto file) and linked in (from the - // callers binary) will be fully resolved. These should be used to make any - // feature-based decisions during code generation. + // global features and language features returned by GetFeatureExtensions will + // be fully resolved. These should be used to make any feature-based decisions + // during code generation. template static const FeatureSet& GetResolvedSourceFeatures(const DescriptorT& desc) { return ::google::protobuf::internal::InternalFeatureHelper::GetFeatures(desc); diff --git a/src/google/protobuf/compiler/code_generator_unittest.cc b/src/google/protobuf/compiler/code_generator_unittest.cc index 4cfc75c9dc..a98214b70c 100644 --- a/src/google/protobuf/compiler/code_generator_unittest.cc +++ b/src/google/protobuf/compiler/code_generator_unittest.cc @@ -7,6 +7,7 @@ #include "google/protobuf/compiler/code_generator.h" +#include #include #include @@ -43,6 +44,9 @@ class TestGenerator : public CodeGenerator { return true; } + uint64_t GetSupportedFeatures() const override { return features_; } + void set_supported_features(uint64_t features) { features_ = features; } + std::vector GetFeatureExtensions() const override { return feature_extensions_; } @@ -65,6 +69,7 @@ class TestGenerator : public CodeGenerator { using CodeGenerator::GetUnresolvedSourceFeatures; private: + uint64_t features_ = CodeGenerator::Feature::FEATURE_SUPPORTS_EDITIONS; Edition minimum_edition_ = PROTOBUF_MINIMUM_EDITION; Edition maximum_edition_ = PROTOBUF_MAXIMUM_EDITION; std::vector feature_extensions_ = { @@ -301,6 +306,19 @@ TEST_F(CodeGeneratorTest, BuildFeatureSetDefaults) { )pb"))); } +TEST_F(CodeGeneratorTest, BuildFeatureSetDefaultsUnsupported) { + TestGenerator generator; + generator.set_supported_features(0); + generator.set_feature_extensions({}); + generator.set_minimum_edition(EDITION_99997_TEST_ONLY); + generator.set_maximum_edition(EDITION_99999_TEST_ONLY); + auto result = generator.BuildFeatureSetDefaults(); + + ASSERT_TRUE(result.ok()) << result.status().message(); + EXPECT_EQ(result->minimum_edition(), PROTOBUF_MINIMUM_EDITION); + EXPECT_EQ(result->maximum_edition(), PROTOBUF_MAXIMUM_EDITION); +} + #include "google/protobuf/port_undef.inc" } // namespace diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index df3bae36e9..a749f79ce4 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -11,6 +11,7 @@ #include "google/protobuf/compiler/command_line_interface.h" +#include #include #include "absl/algorithm/container.h" @@ -295,28 +296,6 @@ bool GetBootstrapParam(const std::string& parameter) { } -bool EnforceEditionsSupport( - const std::string& codegen_name, uint64_t supported_features, - const std::vector& parsed_files) { - if ((supported_features & CodeGenerator::FEATURE_SUPPORTS_EDITIONS) == 0) { - for (const auto fd : parsed_files) { - if (FileDescriptorLegacy(fd).syntax() == - FileDescriptorLegacy::SYNTAX_EDITIONS) { - std::cerr - << fd->name() << ": is an editions file, but code generator " - << codegen_name - << " hasn't been updated to support editions yet. Please ask " - "the owner of this code generator to add support or " - "switch back to proto2/proto3.\n\nSee " - "https://protobuf.dev/editions/overview/ for more information." - << std::endl; - return false; - } - } - } - return true; -} - } // namespace void CommandLineInterface::GetTransitiveDependencies( @@ -1538,24 +1517,26 @@ bool CommandLineInterface::SetupFeatureResolution(DescriptorPool& pool) { for (const auto& output : output_directives_) { if (output.generator == nullptr) continue; if ((output.generator->GetSupportedFeatures() & - CodeGenerator::FEATURE_SUPPORTS_EDITIONS) == 0) { - continue; - } - if (output.generator->GetMinimumEdition() != PROTOBUF_MINIMUM_EDITION) { - ABSL_LOG(ERROR) << "Built-in generator " << output.name - << " specifies a minimum edition " - << output.generator->GetMinimumEdition() - << " which is not the protoc minimum " - << PROTOBUF_MINIMUM_EDITION << "."; - return false; - } - if (output.generator->GetMaximumEdition() != PROTOBUF_MAXIMUM_EDITION) { - ABSL_LOG(ERROR) << "Built-in generator " << output.name - << " specifies a maximum edition " - << output.generator->GetMaximumEdition() - << " which is not the protoc maximum " - << PROTOBUF_MAXIMUM_EDITION << "."; - return false; + CodeGenerator::FEATURE_SUPPORTS_EDITIONS) != 0) { + // Only validate min/max edition on generators that advertise editions + // support. Generators still under development will always use the + // correct values. + if (output.generator->GetMinimumEdition() != minimum_edition) { + ABSL_LOG(ERROR) << "Built-in generator " << output.name + << " specifies a minimum edition " + << output.generator->GetMinimumEdition() + << " which is not the protoc minimum " + << minimum_edition << "."; + return false; + } + if (output.generator->GetMaximumEdition() != maximum_edition) { + ABSL_LOG(ERROR) << "Built-in generator " << output.name + << " specifies a maximum edition " + << output.generator->GetMaximumEdition() + << " which is not the protoc maximum " + << maximum_edition << "."; + return false; + } } for (const FieldDescriptor* ext : output.generator->GetFeatureExtensions()) { @@ -1899,7 +1880,7 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( break; // only for --decode_raw } // --decode (not raw) is handled the same way as the rest of the modes. - PROTOBUF_FALLTHROUGH_INTENDED; + ABSL_FALLTHROUGH_INTENDED; case MODE_ENCODE: case MODE_PRINT: missing_proto_definitions = @@ -2211,7 +2192,9 @@ CommandLineInterface::InterpretArgument(const std::string& name, if (!version_info_.empty()) { std::cout << version_info_ << std::endl; } - std::cout << "libprotoc " << internal::ProtocVersionString(PROTOBUF_VERSION) + std::cout << "libprotoc " + << ::google::protobuf::internal::ProtocVersionString( + PROTOBUF_VERSION) << PROTOBUF_VERSION_SUFFIX << std::endl; return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. @@ -2564,6 +2547,37 @@ bool CommandLineInterface::EnforceProto3OptionalSupport( return true; } +bool CommandLineInterface::EnforceEditionsSupport( + const std::string& codegen_name, uint64_t supported_features, + const std::vector& parsed_files) const { + if (supported_features & CodeGenerator::FEATURE_SUPPORTS_EDITIONS) { + // This generator explicitly supports editions. + return true; + } + if (experimental_editions_) { + // The user has explicitly specified the experimental flag. + return true; + } + for (const auto* fd : parsed_files) { + // Skip enforcement for allowlisted files. + if (IsEarlyEditionsFile(fd->name())) continue; + + if (FileDescriptorLegacy(fd).syntax() == + FileDescriptorLegacy::SYNTAX_EDITIONS) { + std::cerr + << fd->name() << ": is an editions file, but code generator " + << codegen_name + << " hasn't been updated to support editions yet. Please ask " + "the owner of this code generator to add support or " + "switch back to proto2/proto3.\n\nSee " + "https://protobuf.dev/editions/overview/ for more information." + << std::endl; + return false; + } + } + return true; +} + bool CommandLineInterface::GenerateOutput( const std::vector& parsed_files, const OutputDirective& output_directive, diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 58e7a8ab54..107c618fb1 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -222,6 +222,10 @@ class PROTOC_EXPORT CommandLineInterface { const std::string& codegen_name, uint64_t supported_features, const std::vector& parsed_files) const; + bool EnforceEditionsSupport( + const std::string& codegen_name, uint64_t supported_features, + const std::vector& parsed_files) const; + // Return status for ParseArguments() and InterpretArgument(). enum ParseArgumentStatus { diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 23a1c7014a..88e7412176 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -1354,16 +1354,14 @@ TEST_F(CommandLineInterfaceTest, AllowServicesHasService) { ExpectGenerated("test_generator", "", "foo.proto", "Foo"); } -TEST_F(CommandLineInterfaceTest, EditionsAreNotAllowed) { +TEST_F(CommandLineInterfaceTest, NonExperimentalEditions) { CreateTempFile("foo.proto", "edition = \"2023\";\n" "message FooRequest {}\n"); Run("protocol_compiler --proto_path=$tmpdir --test_out=$tmpdir foo.proto"); - ExpectErrorSubstring( - "This file uses editions, but --experimental_editions has not been " - "enabled."); + ExpectErrorSubstring("--experimental_editions has not been enabled"); } TEST_F(CommandLineInterfaceTest, EditionsFlagExplicitTrue) { @@ -1713,12 +1711,10 @@ TEST_F(CommandLineInterfaceTest, GeneratorNoEditionsSupport) { "Doesn't support editions", CodeGenerator::FEATURE_SUPPORTS_EDITIONS); - Run("protocol_compiler --experimental_editions " + Run("protocol_compiler " "--proto_path=$tmpdir foo.proto --no_editions_out=$tmpdir"); - ExpectErrorSubstring( - "code generator --no_editions_out hasn't been updated to support " - "editions"); + ExpectErrorSubstring("--experimental_editions has not been enabled"); } TEST_F(CommandLineInterfaceTest, PluginNoEditionsSupport) { @@ -1730,11 +1726,10 @@ TEST_F(CommandLineInterfaceTest, PluginNoEditionsSupport) { )schema"); SetMockGeneratorTestCase("no_editions"); - Run("protocol_compiler --experimental_editions " + Run("protocol_compiler " "--proto_path=$tmpdir foo.proto --plug_out=$tmpdir"); - ExpectErrorSubstring( - "code generator prefix-gen-plug hasn't been updated to support editions"); + ExpectErrorSubstring("--experimental_editions has not been enabled"); } TEST_F(CommandLineInterfaceTest, EditionDefaults) { diff --git a/src/google/protobuf/compiler/cpp/BUILD.bazel b/src/google/protobuf/compiler/cpp/BUILD.bazel index 8ca37b4b67..fb168b03db 100644 --- a/src/google/protobuf/compiler/cpp/BUILD.bazel +++ b/src/google/protobuf/compiler/cpp/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( name = "names", hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/cpp", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ ":names_internal", @@ -32,7 +32,7 @@ cc_library( "options.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/cpp", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler/rust:__subpackages__", @@ -79,7 +79,7 @@ cc_library( "tracker.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/cpp", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/cpp/enum.cc b/src/google/protobuf/compiler/cpp/enum.cc index a43106f6b2..e23d6e0d64 100644 --- a/src/google/protobuf/compiler/cpp/enum.cc +++ b/src/google/protobuf/compiler/cpp/enum.cc @@ -12,6 +12,7 @@ #include "google/protobuf/compiler/cpp/enum.h" #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc b/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc index 88e2afacaf..62cbbae303 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc @@ -65,9 +65,6 @@ class CordFieldGenerator : public FieldGeneratorBase { void GenerateMergingCode(io::Printer* printer) const override; void GenerateSwappingCode(io::Printer* printer) const override; void GenerateConstructorCode(io::Printer* printer) const override; -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - void GenerateDestructorCode(io::Printer* printer) const override; -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS void GenerateArenaDestructorCode(io::Printer* printer) const override; void GenerateSerializeWithCachedSizesToArray( io::Printer* printer) const override; @@ -244,17 +241,6 @@ void CordFieldGenerator::GenerateConstructorCode(io::Printer* printer) const { } } -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS -void CordFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { - Formatter format(printer, variables_); - if (should_split()) { - // A cord field in the `Split` struct is automatically destroyed when the - // split pointer is deleted and should not be explicitly destroyed here. - return; - } - format("$field$.~Cord();\n"); -} -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS void CordFieldGenerator::GenerateArenaDestructorCode( io::Printer* printer) const { diff --git a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc index d9613e7edb..51a20ce5d0 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc @@ -281,12 +281,6 @@ class RepeatedEnum : public FieldGeneratorBase { p->Emit(R"cc( $field_$.DeleteIfNotDefault(); )cc"); - } else { -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - p->Emit(R"cc( - _internal_mutable_$name$()->~RepeatedField(); - )cc"); -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS } } diff --git a/src/google/protobuf/compiler/cpp/field_generators/map_field.cc b/src/google/protobuf/compiler/cpp/field_generators/map_field.cc index 69a07727e1..13bcd63fe0 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/map_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/map_field.cc @@ -159,11 +159,6 @@ class Map : public FieldGeneratorBase { )cc"); return; } -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - p->Emit(R"cc( - $field_$.~$MapField$(); - )cc"); -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS } void GeneratePrivateMembers(io::Printer* p) const override; diff --git a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc index a7c7935c9a..34c7733eac 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc @@ -14,6 +14,7 @@ #include #include +#include "absl/log/absl_check.h" #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" @@ -55,9 +56,9 @@ std::vector Vars(const FieldDescriptor* field, const Options& opts, ? default_ptr : absl::Substitute("reinterpret_cast($1)", base, default_ptr)}, - {"base_cast", - absl::Substitute("reinterpret_cast<$0*>", - !is_foreign && !weak ? qualified_type : base)}, + {"base_cast", !is_foreign && !weak + ? "" + : absl::Substitute("reinterpret_cast<$0*>", base)}, Sub{"weak_cast", !weak ? "" : absl::Substitute("reinterpret_cast<$0*>", base)} .ConditionalFunctionCall(), @@ -444,26 +445,6 @@ void SingularMessage::GenerateDestructorCode(io::Printer* p) const { using internal::cpp::HasHasbit; -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - -void SingularMessage::GenerateCopyConstructorCode(io::Printer* p) const { - if (has_hasbit_) { - p->Emit(R"cc( - if ((from.$has_hasbit$) != 0) { - _this->$field_$ = new $Submsg$(*from.$field_$); - } - )cc"); - } else { - p->Emit(R"cc( - if (from._internal_has_$name$()) { - _this->$field_$ = new $Submsg$(*from.$field_$); - } - )cc"); - } -} - -#else // !PROTOBUF_EXPLICIT_CONSTRUCTORS - void SingularMessage::GenerateCopyConstructorCode(io::Printer* p) const { if (has_hasbit_) { p->Emit(R"cc( @@ -480,8 +461,6 @@ void SingularMessage::GenerateCopyConstructorCode(io::Printer* p) const { } } -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS - void SingularMessage::GenerateSerializeWithCachedSizesToArray( io::Printer* p) const { if (!is_group()) { @@ -941,10 +920,6 @@ void RepeatedMessage::GenerateDestructorCode(io::Printer* p) const { p->Emit(R"cc( $field_$.DeleteIfNotDefault(); )cc"); - } else { -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - p->Emit("$field_$.~$Weak$RepeatedPtrField();\n"); -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS } } diff --git a/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc b/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc index f96d35511d..f58b9b3eeb 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc @@ -329,12 +329,6 @@ class RepeatedPrimitive final : public FieldGeneratorBase { p->Emit(R"cc( $field_$.DeleteIfNotDefault(); )cc"); - } else { -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - p->Emit(R"cc( - $field_$.~RepeatedField(); - )cc"); -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS } } diff --git a/src/google/protobuf/compiler/cpp/field_generators/string_field.cc b/src/google/protobuf/compiler/cpp/field_generators/string_field.cc index 748a8d6882..426833da15 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/string_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/string_field.cc @@ -596,7 +596,7 @@ void SingularString::GenerateConstructorCode(io::Printer* p) const { $field_$.InitDefault(); )cc"); - if (IsString(field_, *opts_) && EmptyDefault()) { + if (IsString(field_) && EmptyDefault()) { p->Emit(R"cc( #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING $field_$.Set("", GetArena()); @@ -643,14 +643,7 @@ void SingularString::GenerateCopyConstructorCode(io::Printer* p) const { void SingularString::GenerateDestructorCode(io::Printer* p) const { if (is_inlined()) { -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - // Explicitly calls ~InlinedStringField as its automatic call is disabled. - // Destructor has been implicitly skipped as a union. ABSL_DCHECK(!should_split()); - p->Emit(R"cc( - $field_$.~InlinedStringField(); - )cc"); -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS return; } @@ -774,12 +767,6 @@ class RepeatedString : public FieldGeneratorBase { p->Emit(R"cc( $field_$.DeleteIfNotDefault(); )cc"); - } else { -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - p->Emit(R"cc( - _internal_mutable_$name$()->~RepeatedPtrField(); - )cc"); -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS } } diff --git a/src/google/protobuf/compiler/cpp/file.cc b/src/google/protobuf/compiler/cpp/file.cc index ec53d9d0ec..1c88b8a226 100644 --- a/src/google/protobuf/compiler/cpp/file.cc +++ b/src/google/protobuf/compiler/cpp/file.cc @@ -100,7 +100,7 @@ void UnmuteWuninitialized(io::Printer* p) { // in cases where we may declare proto B as a member of proto A using an object, // instead of a pointer. // -// The proto dependencey graph can have cycles. So instead of directly working +// The proto dependency graph can have cycles. So instead of directly working // with protos, we compute strong connected components (SCCs) composed of protos // with mutual dependence. The dependency graph on SCCs is a directed acyclic // graph (DAG) and therefore a topological order can be computed for it i.e. an @@ -909,7 +909,7 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) { GenerateSourceIncludes(p); GenerateSourcePrelude(p); - if (IsAnyMessage(file_, options_)) { + if (IsAnyMessage(file_)) { MuteWuninitialized(p); } @@ -943,7 +943,7 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) { message_generators_[idx]->GenerateSourceInProto2Namespace(p); } - if (IsAnyMessage(file_, options_)) { + if (IsAnyMessage(file_)) { UnmuteWuninitialized(p); } @@ -989,7 +989,7 @@ void FileGenerator::GenerateSource(io::Printer* p) { GetCrossFileReferencesForFile(file_, &refs); GenerateInternalForwardDeclarations(refs, p); - if (IsAnyMessage(file_, options_)) { + if (IsAnyMessage(file_)) { MuteWuninitialized(p); } @@ -1058,7 +1058,7 @@ void FileGenerator::GenerateSource(io::Printer* p) { // @@protoc_insertion_point(global_scope) )cc"); - if (IsAnyMessage(file_, options_)) { + if (IsAnyMessage(file_)) { UnmuteWuninitialized(p); } @@ -1131,13 +1131,14 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* p) { }}, }, R"cc( - const ::uint32_t $tablename$::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - $offsets$, + const ::uint32_t + $tablename$::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + $offsets$, }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { $schemas$, }; @@ -1212,7 +1213,8 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* p) { } }}}, R"cc( - const char $desc_name$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + const char $desc_name$[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { $encoded_file_proto$, }; )cc"); @@ -1406,7 +1408,6 @@ class FileGenerator::ForwardDeclarations { template <> $dllexport_decl $$class$* Arena::CreateMaybeMessage<$class$>(Arena*); )cc"); -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS if (!IsMapEntryMessage(c.second)) { p->Emit({{"class", QualifiedClassName(c.second, options)}}, R"cc( template <> @@ -1414,7 +1415,6 @@ class FileGenerator::ForwardDeclarations { Arena*, const $class$&); )cc"); } -#endif // PROTOBUF_EXPLICIT_CONSTRUCTORS } } } diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc index 2c8d275114..c14e064c57 100644 --- a/src/google/protobuf/compiler/cpp/helpers.cc +++ b/src/google/protobuf/compiler/cpp/helpers.cc @@ -921,6 +921,23 @@ bool IsStringInliningEnabled(const Options& options) { return options.force_inline_string || IsProfileDriven(options); } +bool CanStringBeInlined(const FieldDescriptor* field) { + // TODO: Handle inlining for any.proto. + if (IsAnyMessage(field->containing_type())) return false; + if (field->containing_type()->options().map_entry()) return false; + if (field->is_repeated()) return false; + + // We rely on has bits to distinguish field presence for release_$name$. When + // there is no hasbit, we cannot use the address of the string instance when + // the field has been inlined. + if (!internal::cpp::HasHasbit(field)) return false; + + if (!IsString(field)) return false; + if (!field->default_value_string().empty()) return false; + + return true; +} + bool IsStringInlined(const FieldDescriptor* field, const Options& options) { (void)field; (void)options; @@ -1148,13 +1165,13 @@ bool IsStringOrMessage(const FieldDescriptor* field) { return false; } -bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options) { +bool IsAnyMessage(const FileDescriptor* descriptor) { return descriptor->name() == kAnyProtoFile; } -bool IsAnyMessage(const Descriptor* descriptor, const Options& options) { +bool IsAnyMessage(const Descriptor* descriptor) { return descriptor->name() == kAnyMessageName && - IsAnyMessage(descriptor->file(), options); + IsAnyMessage(descriptor->file()); } bool IsWellKnownMessage(const FileDescriptor* file) { diff --git a/src/google/protobuf/compiler/cpp/helpers.h b/src/google/protobuf/compiler/cpp/helpers.h index 9b7483537d..4c590cdc76 100644 --- a/src/google/protobuf/compiler/cpp/helpers.h +++ b/src/google/protobuf/compiler/cpp/helpers.h @@ -331,7 +331,7 @@ inline bool IsCord(const FieldDescriptor* field) { internal::cpp::EffectiveStringCType(field) == FieldOptions::CORD; } -inline bool IsString(const FieldDescriptor* field, const Options& options) { +inline bool IsString(const FieldDescriptor* field) { return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && internal::cpp::EffectiveStringCType(field) == FieldOptions::STRING; } @@ -355,9 +355,21 @@ float GetPresenceProbability(const FieldDescriptor* field, bool IsStringInliningEnabled(const Options& options); -// Returns true if `field` should be inlined based on PDProto profile. +// Returns true if the provided field is a singular string and can be inlined. +bool CanStringBeInlined(const FieldDescriptor* field); + +// Returns true if `field` is a string field that can and should be inlined +// based on PDProto profile. bool IsStringInlined(const FieldDescriptor* field, const Options& options); +// Returns true if `field` should be inlined based on PDProto profile. +// Currently we only enable inlining for string fields backed by a std::string +// instance, but in the future we may expand this to message types. +inline bool IsFieldInlined(const FieldDescriptor* field, + const Options& options) { + return IsStringInlined(field, options); +} + // Does the given FileDescriptor use lazy fields? bool HasLazyFields(const FileDescriptor* file, const Options& options, MessageSCCAnalyzer* scc_analyzer); @@ -529,8 +541,8 @@ inline std::string MakeVarintCachedSizeFieldName(const FieldDescriptor* field, // while the two functions below use FileDescriptor::name(). In a sane world the // two approaches should be equivalent. But if you are dealing with descriptors // from untrusted sources, you might need to match semantics across libraries. -bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options); -bool IsAnyMessage(const Descriptor* descriptor, const Options& options); +bool IsAnyMessage(const FileDescriptor* descriptor); +bool IsAnyMessage(const Descriptor* descriptor); bool IsWellKnownMessage(const FileDescriptor* descriptor); diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index 08fd28f69b..b5f89a9da2 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -299,7 +300,7 @@ bool IsCrossFileMaybeMap(const FieldDescriptor* field) { bool HasNonSplitOptionalString(const Descriptor* desc, const Options& options) { for (const auto* field : FieldRange(desc)) { - if (IsString(field, options) && !field->is_repeated() && + if (IsString(field) && !field->is_repeated() && !field->real_containing_oneof() && !ShouldSplit(field, options)) { return true; } @@ -1280,12 +1281,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { "explicit PROTOBUF_CONSTEXPR " "$classname$(::$proto_ns$::internal::ConstantInitialized);\n" "\n" -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS "inline $classname$(const $classname$& from)\n" " : $classname$(nullptr, from) {}\n" -#else // PROTOBUF_EXPLICIT_CONSTRUCTORS - "$classname$(const $classname$& from);\n" -#endif // PROTOBUF_EXPLICIT_CONSTRUCTORS "$classname$($classname$&& from) noexcept\n" " : $classname$() {\n" " *this = ::std::move(from);\n" @@ -1384,7 +1381,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { "\n", index_in_file_messages_); - if (IsAnyMessage(descriptor_, options_)) { + if (IsAnyMessage(descriptor_)) { format( "// implements Any -----------------------------------------------\n" "\n"); @@ -1532,7 +1529,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { if (!HasSimpleBaseClass(descriptor_, options_)) { format( - "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;\n" + "ABSL_ATTRIBUTE_REINITIALIZES void Clear() final;\n" "bool IsInitialized() const final;\n" "\n" "::size_t ByteSizeLong() const final;\n"); @@ -1578,15 +1575,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { // we rely on. "protected:\n" "explicit $classname$(::$proto_ns$::Arena* arena);\n" -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS "$classname$(::$proto_ns$::Arena* arena, const $classname$& from);\n" -#else // PROTOBUF_EXPLICIT_CONSTRUCTORS - "inline $classname$(::$proto_ns$::Arena* arena," - " const $classname$& from)\n" - " : $classname$(arena) {\n" - " MergeFrom(from);\n" - "}\n" -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS ); switch (NeedsArenaDestructor()) { @@ -1614,26 +1603,20 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { break; } + if (!HasSimpleBaseClass(descriptor_, options_)) { + p->Emit(R"cc( + const ::$proto_ns$::MessageLite::ClassData* GetClassData() const final; + )cc"); + } + format( "public:\n" "\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - if (HasGeneratedMethods(descriptor_->file(), options_) && - !HasSimpleBaseClass(descriptor_, options_)) { - format( - "static const ClassData _class_data_;\n" - "const ::$proto_ns$::Message::ClassData*" - "GetClassData() const final;\n" - "\n"); - } format( "::$proto_ns$::Metadata GetMetadata() const final;\n" "\n"); - } else { - format( - "std::string GetTypeName() const final;\n" - "\n"); } if (ShouldSplit(descriptor_, options_)) { @@ -1750,14 +1733,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { // alignment. // (3) members assumed to align to 4 bytes. -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS format("struct $dllexport_decl $Impl_ {\n"); -#else - format("struct Impl_ {\n"); -#endif format.Indent(); -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS // TODO: check if/when there is a need for an outline dtor. format(R"cc( inline explicit constexpr Impl_( @@ -1767,7 +1745,6 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { inline explicit Impl_($pbi$::InternalVisibility visibility, ::$proto_ns$::Arena* arena, const Impl_& from); )cc"); -#endif // PROTOBUF_EXPLICIT_CONSTRUCTORS // Members assumed to align to 8 bytes: @@ -1870,7 +1847,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { format("::$proto_ns$::internal::WeakFieldMap _weak_field_map_;\n"); } // Generate _any_metadata_ for the Any type. - if (IsAnyMessage(descriptor_, options_)) { + if (IsAnyMessage(descriptor_)) { format("::$proto_ns$::internal::AnyMetadata _any_metadata_;\n"); } @@ -1983,7 +1960,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* p) { return; } - if (IsAnyMessage(descriptor_, options_)) { + if (IsAnyMessage(descriptor_)) { if (HasDescriptorMethods(descriptor_->file(), options_)) { format( "bool $classname$::GetAnyFieldDescriptors(\n" @@ -2066,6 +2043,8 @@ void MessageGenerator::GenerateClassMethods(io::Printer* p) { format("\n"); } + GenerateClassData(p); + if (HasGeneratedMethods(descriptor_->file(), options_)) { GenerateClear(p); format("\n"); @@ -2141,12 +2120,6 @@ void MessageGenerator::GenerateClassMethods(io::Printer* p) { "}\n", index_in_file_messages_); } - } else { - format( - "std::string $classname$::GetTypeName() const {\n" - " return \"$full_name$\";\n" - "}\n" - "\n"); } if (HasTracker(descriptor_, options_)) { @@ -2272,169 +2245,6 @@ std::pair MessageGenerator::GenerateOffsets(io::Printer* p) { return std::make_pair(entries, offsets); } -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - -void MessageGenerator::GenerateSharedConstructorCode(io::Printer* p) { - if (HasSimpleBaseClass(descriptor_, options_)) return; - - p->Emit( - { - {"impl_init", - [&] { - // Note: any fields without move/copy constructors can't be - // explicitly aggregate initialized pre-C++17. - if (descriptor_->extension_range_count() > 0) { - p->Emit(R"cc( - /*decltype($extensions$)*/ {::_pbi::ArenaInitialized(), arena}, - )cc"); - } - if (!inlined_string_indices_.empty()) { - p->Emit(R"cc( - decltype($inlined_string_donated_array$){}, - )cc"); - } - bool need_to_emit_cached_size = - !HasSimpleBaseClass(descriptor_, options_); - if (!has_bit_indices_.empty()) { - p->Emit(R"cc( - decltype($has_bits$){}, - )cc"); - if (need_to_emit_cached_size) { - p->Emit(R"cc( - /*decltype($cached_size$)*/ {}, - )cc"); - need_to_emit_cached_size = false; - } - } - - // Initialize member variables with arena constructor. - for (const auto* field : optimized_order_) { - if (ShouldSplit(field, options_)) { - continue; - } - field_generators_.get(field).GenerateAggregateInitializer(p); - } - if (ShouldSplit(descriptor_, options_)) { - // 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. - p->Emit( - {{"instance", DefaultInstanceName(descriptor_, options_, - /*split=*/true)}}, - R"cc( - decltype($split$){const_cast( - reinterpret_cast(&$instance$))}, - )cc"); - } - for (const auto* oneof : OneOfRange(descriptor_)) { - p->Emit({{"name", oneof->name()}}, - R"cc( - decltype(_impl_.$name$_){}, - )cc"); - } - - if (need_to_emit_cached_size) { - p->Emit(R"cc( - /*decltype($cached_size$)*/ {}, - )cc"); - } - - if (descriptor_->real_oneof_decl_count() != 0) { - p->Emit(R"cc( - /*decltype($oneof_case$)*/ {}, - )cc"); - } - if (num_weak_fields_ > 0) { - p->Emit(R"cc( - decltype($weak_field_map$){arena}, - )cc"); - } - if (IsAnyMessage(descriptor_, options_)) { - // AnyMetadata has no move constructor. - p->Emit(R"cc( - /*decltype($any_metadata$)*/ {&_impl_.type_url_, - &_impl_.value_}, - )cc"); - } - }}, - {"inlined_strings_init", - [&] { - if (inlined_string_indices_.empty()) return; - // Donate inline string fields. - // The last bit is the tracking bit for registering ArenaDtor. The - // bit is 1 means ArenaDtor is not registered on construction, and - // on demand register is needed. - p->Emit( - { - {"mask", - NeedsArenaDestructor() == ArenaDtorNeeds::kOnDemand - ? "~0u" - : "0xFFFFFFFEu"}, - {"init_body", - [&] { - for (size_t i = 1; i < InlinedStringDonatedSize(); - ++i) { - p->Emit({{"i", i}}, - R"cc( - $inlined_string_donated_array$[$i$] = ~0u; - )cc"); - } - }}, - }, - R"cc( - if (arena != nullptr) { - $inlined_string_donated_array$[0] = $mask$; - $init_body$; - } - )cc"); - }}, - {"field_ctor_code", - [&] { - for (const FieldDescriptor* field : optimized_order_) { - if (ShouldSplit(field, options_)) { - continue; - } - field_generators_.get(field).GenerateConstructorCode(p); - } - }}, - {"force_allocation", - [&] { - if (!ShouldForceAllocationOnConstruction(descriptor_, options_)) - return; - p->Emit(R"cc( - //~ force alignment -#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION - $mutable_unknown_fields$; -#endif // PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION - )cc"); - }}, - {"clear_oneofs", - [&] { - for (auto oneof : OneOfRange(descriptor_)) { - p->Emit({{"name", oneof->name()}}, - R"cc( - clear_has_$name$(); - )cc"); - } - }}, - }, - R"cc( - inline void $classname$::SharedCtor(::_pb::Arena* arena) { - (void)arena; - new (&_impl_) Impl_{ - $impl_init$, - }; - $inlined_strings_init$; - $field_ctor_code$; - $force_allocation$; - $clear_oneofs$; - } - )cc"); -} - -#else // !PROTOBUF_EXPLICIT_CONSTRUCTORS void MessageGenerator::GenerateZeroInitFields(io::Printer* p) const { using Iterator = decltype(optimized_order_.begin()); @@ -2622,7 +2432,7 @@ void MessageGenerator::GenerateImplMemberInit(io::Printer* p, }; auto init_any_metadata = [&] { - if (IsAnyMessage(descriptor_, options_)) { + if (IsAnyMessage(descriptor_)) { separator(); p->Emit("_any_metadata_{&type_url_, &value_}"); } @@ -2661,8 +2471,6 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* p) { )cc"); } -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS - void MessageGenerator::GenerateInitDefaultSplitInstance(io::Printer* p) { if (!ShouldSplit(descriptor_, options_)) return; @@ -2688,15 +2496,6 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* p) { }; p->Emit( { - {"extensions_dtor", - [&] { -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - if (descriptor_->extension_range_count() == 0) return; - p->Emit(R"cc( - $extensions$.~ExtensionSet(); - )cc"); -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS - }}, {"field_dtors", [&] { emit_field_dtors(/* split_fields= */ false); }}, {"split_field_dtors", [&] { @@ -2733,31 +2532,15 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* p) { $weak_field_map$.ClearAll(); )cc"); }}, - {"any_metadata_dtor", - [&] { -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - if (!IsAnyMessage(descriptor_, options_)) return; - p->Emit(R"cc( - $any_metadata$.~AnyMetadata(); - )cc"); -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS - }}, - {"impl_dtor", - [&] { -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS - p->Emit("_impl_.~Impl_();\n"); -#endif // PROTOBUF_EXPLICIT_CONSTRUCTORS - }}, + {"impl_dtor", [&] { p->Emit("_impl_.~Impl_();\n"); }}, }, R"cc( inline void $classname$::SharedDtor() { $DCHK$(GetArena() == nullptr); - $extensions_dtor$; $field_dtors$; $split_field_dtors$; $oneof_field_dtors$; $weak_fields_dtor$; - $any_metadata_dtor$; $impl_dtor$; } )cc"); @@ -2855,91 +2638,6 @@ void MessageGenerator::GenerateConstexprConstructor(io::Printer* p) { return; } -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - - bool need_to_emit_cached_size = !HasSimpleBaseClass(descriptor_, options_); - p->Emit( - { - {"init_body", - [&] { - p->Emit("\n"); - auto indent = p->WithIndent(); - - if (descriptor_->extension_range_count() > 0) { - p->Emit(R"cc( - /*decltype($extensions$)*/ {}, - )cc"); - } - if (!inlined_string_indices_.empty()) { - p->Emit(R"cc( - /*decltype($inlined_string_donated_array$)*/ {}, - )cc"); - } - if (!has_bit_indices_.empty()) { - p->Emit(R"cc( - /*decltype($has_bits$)*/ {}, - )cc"); - if (need_to_emit_cached_size) { - p->Emit(R"cc( - /*decltype($cached_size$)*/ {}, - )cc"); - need_to_emit_cached_size = false; - } - } - for (auto* field : optimized_order_) { - if (ShouldSplit(field, options_)) { - continue; - } - field_generators_.get(field) - .GenerateConstexprAggregateInitializer(p); - } - if (ShouldSplit(descriptor_, options_)) { - p->Emit({{"name", DefaultInstanceName(descriptor_, options_, - /*split=*/true)}}, - R"cc( - /*decltype($split$)*/ const_cast( - &$name$._instance), - )cc"); - } - for (auto* oneof : OneOfRange(descriptor_)) { - p->Emit({{"name", oneof->name()}}, - R"cc( - /*decltype(_impl_.$name$_)*/ {}, - )cc"); - } - if (need_to_emit_cached_size) { - p->Emit(R"cc( - /*decltype($cached_size$)*/ {}, - )cc"); - } - if (descriptor_->real_oneof_decl_count() != 0) { - p->Emit(R"cc( - /*decltype($oneof_case$)*/ {}, - )cc"); - } - if (num_weak_fields_) { - p->Emit(R"cc( - /*decltype($weak_field_map$)*/ {}, - )cc"); - } - if (IsAnyMessage(descriptor_, options_)) { - p->Emit(R"cc( - /*decltype($any_metadata$)*/ {&_impl_.type_url_, - &_impl_.value_}, - )cc"); - } - }}, - }, - R"cc( - //~ Templatize constexpr constructor as a workaround for a bug in gcc 12 - //~ (warning in gcc 13). - template - $constexpr$ $classname$::$classname$(::_pbi::ConstantInitialized) - : _impl_{$init_body$} {} - )cc"); - -#else // !PROTOBUF_EXPLICIT_CONSTRUCTORS - // Generate Impl_::Imp_(::_pbi::ConstantInitialized); // We use separate p->Emit() calls for LF and #ifdefs as they result in // awkward layout and more awkward indenting of the function statement. @@ -2959,73 +2657,6 @@ void MessageGenerator::GenerateConstexprConstructor(io::Printer* p) { $constexpr$ $classname$::$classname$(::_pbi::ConstantInitialized) : _impl_(::_pbi::ConstantInitialized()) {} )cc"); - -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS -} - -void MessageGenerator::GenerateCopyConstructorBody(io::Printer* p) const { - Formatter format(p); - - const RunMap runs = - FindRuns(optimized_order_, [this](const FieldDescriptor* field) { - return IsPOD(field) && !ShouldSplit(field, options_); - }); - - std::string pod_template = - "::memcpy(&$first$, &from.$first$,\n" - " static_cast<::size_t>(reinterpret_cast(&$last$) -\n" - " reinterpret_cast(&$first$)) + sizeof($last$));\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) { - const FieldDescriptor* field = optimized_order_[i]; - if (ShouldSplit(field, options_)) { - continue; - } - const auto it = runs.find(field); - - // We only apply the memset technique to runs of more than one field, as - // assignment is better than memset for generated code clarity. - if (it != runs.end() && it->second > 1) { - // Use a memset, then skip run_length fields. - const size_t run_length = it->second; - const std::string first_field_name = - FieldMemberName(field, /*cold=*/false); - const std::string last_field_name = - FieldMemberName(optimized_order_[i + run_length - 1], /*cold=*/false); - - auto v = p->WithVars({ - {"first", first_field_name}, - {"last", last_field_name}, - }); - format(pod_template.c_str()); - - i += run_length - 1; - // ++i at the top of the loop. - } else { - field_generators_.get(field).GenerateCopyConstructorCode(p); - } - } - - if (ShouldSplit(descriptor_, options_)) { - format("if (PROTOBUF_PREDICT_FALSE(!from.IsSplitMessageDefault())) {\n"); - format.Indent(); - format("_this->PrepareSplitMessageForWrite();\n"); - // TODO: cache the split pointers. - for (auto field : optimized_order_) { - if (ShouldSplit(field, options_)) { - field_generators_.get(field).GenerateCopyConstructorCode(p); - } - } - format.Outdent(); - format("}\n"); - } } bool MessageGenerator::ImplHasCopyCtor() const { @@ -3057,128 +2688,6 @@ bool MessageGenerator::ImplHasCopyCtor() const { return true; } -void MessageGenerator::GenerateCopyConstructorBodyImpl(io::Printer* p) const { - if (!HasImplData(descriptor_, options_)) return; - - p->Emit( - {{"initializer", - [&] { - if (descriptor_->extension_range_count() > 0) { - p->Emit(R"cc( - /*decltype($extensions$)*/ {}, - )cc"); - } - if (!inlined_string_indices_.empty()) { - // Do not copy inlined_string_donated_, because this is not an - // arena constructor. - p->Emit(R"cc( - decltype($inlined_string_donated_array$){}, - )cc"); - } - - bool need_to_emit_cached_size = - !HasSimpleBaseClass(descriptor_, options_); - if (!has_bit_indices_.empty()) { - p->Emit(R"cc( - decltype($has_bits$){from.$has_bits$}, - )cc"); - if (need_to_emit_cached_size) { - p->Emit(R"cc( - /*decltype($cached_size$)*/ {}, - )cc"); - need_to_emit_cached_size = false; - } - } - // Initialize member variables with arena constructor. - for (const auto* field : optimized_order_) { - if (ShouldSplit(field, options_)) continue; - field_generators_.get(field).GenerateCopyAggregateInitializer(p); - } - if (ShouldSplit(descriptor_, options_)) { - p->Emit({{"name", DefaultInstanceName(descriptor_, options_, - /*split=*/true)}}, - R"cc( - decltype($split$){const_cast( - reinterpret_cast(&$name$))}, - )cc"); - } - for (auto oneof : OneOfRange(descriptor_)) { - p->Emit({{"name", oneof->name()}}, - R"cc( - decltype(_impl_.$name$_){}, - )cc"); - } - if (need_to_emit_cached_size) { - p->Emit(R"cc( - /*decltype($cached_size$)*/ {}, - )cc"); - need_to_emit_cached_size = false; - } - if (descriptor_->real_oneof_decl_count() > 0) { - p->Emit(R"cc( - /*decltype($oneof_case$)*/ {}, - )cc"); - } - if (num_weak_fields_ > 0) { - p->Emit(R"cc( - decltype($weak_field_map$){from.$weak_field_map$}, - )cc"); - } - if (IsAnyMessage(descriptor_, options_)) { - p->Emit(R"cc( - /*decltype($any_metadata$)*/ { - &_impl_.type_url_, - &_impl_.value_, - }, - )cc"); - } - }}}, - R"cc( - new (&_impl_) Impl_{ - $initializer$, - }; - )cc"); -} - -void MessageGenerator::GenerateCopyConstructorBodyOneofs(io::Printer* p) const { - // Copy oneof fields. Oneof field requires oneof case check. - for (const auto* oneof : OneOfRange(descriptor_)) { - p->Emit( - { - {"name", oneof->name()}, - {"NAME", absl::AsciiStrToUpper(oneof->name())}, - {"cases", - [&] { - for (const auto* field : FieldRange(oneof)) { - p->Emit( - {{"Name", UnderscoresToCamelCase(field->name(), true)}, - {"body", - [&] { - field_generators_.get(field).GenerateMergingCode(p); - }}}, - R"cc( - case k$Name$: { - $body$; - break; - } - )cc"); - } - }}, - }, - R"cc( - clear_has_$name$(); - switch (from.$name$_case()) { - $cases$; - case $NAME$_NOT_SET: { - break; - } - } - )cc"); - } -} - -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS - void MessageGenerator::GenerateCopyInitFields(io::Printer* p) const { auto begin = optimized_order_.begin(); auto end = optimized_order_.end(); @@ -3412,8 +2921,6 @@ void MessageGenerator::GenerateArenaEnabledCopyConstructor(io::Printer* p) { )cc"); } -#endif // PROTOBUF_EXPLICIT_CONSTRUCTORS - void MessageGenerator::GenerateStructors(io::Printer* p) { p->Emit( { @@ -3440,57 +2947,6 @@ void MessageGenerator::GenerateStructors(io::Printer* p) { )cc"); // Generate the copy constructor. -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS - if (UsingImplicitWeakFields(descriptor_->file(), options_)) { - // If we are in lite mode and using implicit weak fields, we generate a - // one-liner copy constructor that delegates to MergeFrom. This saves some - // code size and also cuts down on the complexity of implicit weak fields. - // We might eventually want to do this for all lite protos. - p->Emit(R"cc( - $classname$::$classname$(const $classname$& from) : $classname$() { - MergeFrom(from); - } - )cc"); - } else if (ImplHasCopyCtor()) { - p->Emit(R"cc( - $classname$::$classname$(const $classname$& from) - : $superclass$(), _impl_(from._impl_) { - _internal_metadata_.MergeFrom<$unknown_fields_type$>( - from._internal_metadata_); - // @@protoc_insertion_point(copy_constructor:$full_name$) - } - )cc"); - } else { - p->Emit( - { - {"copy_impl", [&] { GenerateCopyConstructorBodyImpl(p); }}, - {"copy_extensions", - [&] { - if (descriptor_->extension_range_count() == 0) return; - p->Emit(R"cc( - $extensions$.MergeFrom(internal_default_instance(), - from.$extensions$); - )cc"); - }}, - {"copy_body", [&] { GenerateCopyConstructorBody(p); }}, - {"copy_oneofs", [&] { GenerateCopyConstructorBodyOneofs(p); }}, - }, - R"cc( - $classname$::$classname$(const $classname$& from) : $superclass$() { - $classname$* const _this = this; - (void)_this; - $copy_impl$; - _internal_metadata_.MergeFrom<$unknown_fields_type$>( - from._internal_metadata_); - $copy_extensions$; - $copy_body$; - $copy_oneofs$; - - // @@protoc_insertion_point(copy_constructor:$full_name$) - } - )cc"); - } -#else // !PROTOBUF_EXPLICIT_CONSTRUCTORS if (UsingImplicitWeakFields(descriptor_->file(), options_)) { // If we are in lite mode and using implicit weak fields, we generate a // one-liner copy constructor that delegates to MergeFrom. This saves some @@ -3516,7 +2972,6 @@ void MessageGenerator::GenerateStructors(io::Printer* p) { } else { GenerateArenaEnabledCopyConstructor(p); } -#endif // !PROTOBUF_EXPLICIT_CONSTRUCTORS // Generate the shared constructor code. GenerateSharedConstructorCode(p); @@ -3554,7 +3009,6 @@ void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* p) { Formatter format(p); if (ShouldGenerateExternSpecializations(options_) && ShouldGenerateClass(descriptor_, options_)) { -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS format(R"cc( template <> PROTOBUF_NOINLINE $classtype$* Arena::CreateMaybeMessage<$classtype$>( @@ -3577,14 +3031,6 @@ void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* p) { } )cc"); } -#else // PROTOBUF_EXPLICIT_CONSTRUCTORS - format( - "template<> " - "PROTOBUF_NOINLINE $classtype$*\n" - "Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n" - " return Arena::CreateMessageInternal< $classtype$ >(arena);\n" - "}\n"); -#endif // PROTOBUF_EXPLICIT_CONSTRUCTORS } } @@ -3946,21 +3392,27 @@ void MessageGenerator::GenerateSwap(io::Printer* p) { format("}\n"); } -void MessageGenerator::GenerateMergeFrom(io::Printer* p) { +void MessageGenerator::GenerateClassData(io::Printer* p) { Formatter format(p); if (HasSimpleBaseClass(descriptor_, options_)) return; - if (HasDescriptorMethods(descriptor_->file(), options_)) { - // We don't override the generalized MergeFrom (aka that which - // takes in the Message base class as a parameter); instead we just - // let the base Message::MergeFrom take care of it. The base MergeFrom - // knows how to quickly confirm the types exactly match, and if so, will - // use GetClassData() to retrieve the address of MergeImpl, which calls - // the fast MergeFrom overload. Most callers avoid all this by passing - // a "from" message that is the same type as the message being merged - // into, rather than a generic Message. + const auto class_data_members = [&] { p->Emit( { + {"merge_impl", + [&] { + // TODO: This check is not needed once we migrate + // CheckTypeAndMergeFrom to ClassData fully. + if (HasDescriptorMethods(descriptor_->file(), options_)) { + p->Emit(R"cc( + $classname$::MergeImpl, + )cc"); + } else { + p->Emit(R"cc( + nullptr, // MergeImpl + )cc"); + } + }}, {"on_demand_register_arena_dtor", [&] { if (NeedsArenaDestructor() == ArenaDtorNeeds::kOnDemand) { @@ -3973,17 +3425,67 @@ void MessageGenerator::GenerateMergeFrom(io::Printer* p) { )cc"); } }}, + {"descriptor_methods", + [&] { + if (HasDescriptorMethods(descriptor_->file(), options_)) { + p->Emit(R"cc( + &::$proto_ns$::Message::kDescriptorMethods, + )cc"); + } else { + p->Emit(R"cc( + nullptr, // DescriptorMethods + )cc"); + } + }}, }, R"cc( - const ::$proto_ns$::Message::ClassData $classname$::_class_data_ = { - $classname$::MergeImpl, - $on_demand_register_arena_dtor$, - }; - const ::$proto_ns$::Message::ClassData* $classname$::GetClassData() const { - return &_class_data_; + $merge_impl$, $on_demand_register_arena_dtor$, $descriptor_methods$, + )cc"); + }; + + if (HasDescriptorMethods(descriptor_->file(), options_)) { + p->Emit( + {{"class_data_members", class_data_members}}, + R"cc( + const ::$proto_ns$::MessageLite::ClassData* + $classname$::GetClassData() const { + PROTOBUF_CONSTINIT static const ::$proto_ns$::MessageLite::ClassData + data = { + $class_data_members$, + }; + return &data; } )cc"); } else { + p->Emit( + { + {"class_data_members", class_data_members}, + {"type_size", descriptor_->full_name().size() + 1}, + }, + R"cc( + const ::$proto_ns$::MessageLite::ClassData* + $classname$::GetClassData() const { + struct ClassData_ { + ::$proto_ns$::MessageLite::ClassData header; + char type_name[$type_size$]; + }; + PROTOBUF_CONSTINIT static const ClassData_ data = { + { + $class_data_members$, + }, + "$full_name$", + }; + + return &data.header; + } + )cc"); + } +} + +void MessageGenerator::GenerateMergeFrom(io::Printer* p) { + Formatter format(p); + + if (!HasDescriptorMethods(descriptor_->file(), options_)) { // Generate CheckTypeAndMergeFrom(). format( "void $classname$::CheckTypeAndMergeFrom(\n" diff --git a/src/google/protobuf/compiler/cpp/message.h b/src/google/protobuf/compiler/cpp/message.h index 820a954c12..4c404adcb9 100644 --- a/src/google/protobuf/compiler/cpp/message.h +++ b/src/google/protobuf/compiler/cpp/message.h @@ -89,14 +89,12 @@ class MessageGenerator { // Generate constructors and destructor. void GenerateStructors(io::Printer* p); -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS void GenerateZeroInitFields(io::Printer* p) const; void GenerateCopyInitFields(io::Printer* p) const; void GenerateImplMemberInit(io::Printer* p, InitType init_type); void GenerateArenaEnabledCopyConstructor(io::Printer* p); -#endif // PROTOBUF_EXPLICIT_CONSTRUCTORS // The compiler typically generates multiple copies of each constructor and // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx @@ -119,6 +117,7 @@ class MessageGenerator { void GenerateSerializeWithCachedSizesBody(io::Printer* p); void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* p); void GenerateByteSize(io::Printer* p); + void GenerateClassData(io::Printer* p); void GenerateMergeFrom(io::Printer* p); void GenerateClassSpecificMergeImpl(io::Printer* p); void GenerateCopyFrom(io::Printer* p); @@ -152,11 +151,6 @@ class MessageGenerator { // Returns whether impl_ has a copy ctor. bool ImplHasCopyCtor() const; - // Generates the body of the message's copy constructor. - void GenerateCopyConstructorBody(io::Printer* p) const; - void GenerateCopyConstructorBodyImpl(io::Printer* p) const; - void GenerateCopyConstructorBodyOneofs(io::Printer* p) const; - // Returns the level that this message needs ArenaDtor. If the message has // a field that is not arena-exclusive, it needs an ArenaDtor // (go/proto-destructor). diff --git a/src/google/protobuf/compiler/cpp/options.h b/src/google/protobuf/compiler/cpp/options.h index 5ae95353fb..30be9c0bb2 100644 --- a/src/google/protobuf/compiler/cpp/options.h +++ b/src/google/protobuf/compiler/cpp/options.h @@ -54,6 +54,7 @@ struct Options { bool opensource_runtime = false; bool annotate_accessor = false; bool force_split = false; + bool profile_driven_cluster_aux_subtable = false; #ifdef PROTOBUF_STABLE_EXPERIMENTS bool force_eagerly_verified_lazy = true; bool force_inline_string = true; diff --git a/src/google/protobuf/compiler/cpp/parse_function_generator.cc b/src/google/protobuf/compiler/cpp/parse_function_generator.cc index 1b8ffc4c5e..a8074dfce7 100644 --- a/src/google/protobuf/compiler/cpp/parse_function_generator.cc +++ b/src/google/protobuf/compiler/cpp/parse_function_generator.cc @@ -116,11 +116,9 @@ ParseFunctionGenerator::ParseFunctionGenerator( if (should_generate_tctable()) { tc_table_info_.reset(new TailCallTableInfo( descriptor_, ordered_fields_, - { - /* is_lite */ GetOptimizeFor(descriptor->file(), options_) == - FileOptions::LITE_RUNTIME, - /* uses_codegen */ true, - }, + {/* is_lite */ GetOptimizeFor(descriptor->file(), options_) == + FileOptions::LITE_RUNTIME, + /* uses_codegen */ true, options_.profile_driven_cluster_aux_subtable}, GeneratedOptionProvider(this), has_bit_indices, inlined_string_indices)); } @@ -235,9 +233,12 @@ void ParseFunctionGenerator::GenerateDataDecls(io::Printer* p) { // Since most (>80%) messages are never present, messages that are // present are considered hot enough to be clustered together. if (IsPresentMessage(descriptor_, options_)) { - p->Emit("PROTOBUF_SECTION_VARIABLE(proto_parse_table_hot)"); + p->Emit( + "ABSL_ATTRIBUTE_SECTION_VARIABLE(proto_parse_table_hot)"); } else { - p->Emit("PROTOBUF_SECTION_VARIABLE(proto_parse_table_lukewarm)"); + p->Emit( + "ABSL_ATTRIBUTE_SECTION_VARIABLE(proto_parse_table_" + "lukewarm)"); } }}, {"table_size_log2", tc_table_info_->table_size_log2}, diff --git a/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.cc b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.cc new file mode 100644 index 0000000000..8af6b57380 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.cc @@ -0,0 +1,349 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2023 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "google/protobuf/compiler/cpp/tools/analyze_profile_proto.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "google/protobuf/testing/file.h" +#include "google/protobuf/testing/file.h" +#include "google/protobuf/compiler/access_info_map.h" +#include "google/protobuf/compiler/split_map.h" +#include "google/protobuf/compiler/profile_bootstrap.pb.h" +#include "absl/log/absl_log.h" +#include "absl/log/log.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/cord.h" +#include "absl/strings/str_replace.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/cpp/cpp_access_info_parse_helper.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "third_party/re2/re2.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace tools { + +namespace { + +enum PDProtoScale { kNever, kRarely, kDefault, kLikely }; + +struct PDProtoAnalysis { + PDProtoScale presence = PDProtoScale::kDefault; + PDProtoScale usage = PDProtoScale::kDefault; +}; + +std::ostream& operator<<(std::ostream& s, PDProtoScale scale) { + switch (scale) { + case PDProtoScale::kNever: + return s << "NEVER"; + case PDProtoScale::kRarely: + return s << "RARELY"; + case PDProtoScale::kDefault: + return s << "DEFAULT"; + case PDProtoScale::kLikely: + return s << "LIKELY"; + } + return s; +} + +enum PDProtoOptimization { kNone, kUnverifiedLazy, kLazy, kInline, kSplit }; + +std::ostream& operator<<(std::ostream& s, PDProtoOptimization optimization) { + switch (optimization) { + case PDProtoOptimization::kNone: + return s << "NONE"; + case PDProtoOptimization::kLazy: + return s << "LAZY"; + case PDProtoOptimization::kUnverifiedLazy: + return s << "UNVERIFIED_LAZY"; + case PDProtoOptimization::kInline: + return s << "INLINE"; + case PDProtoOptimization::kSplit: + return s << "SPLIT"; + } + return s; +} + +class PDProtoAnalyzer { + public: + explicit PDProtoAnalyzer(const AccessInfo& access_info) + : info_map_(access_info) { + info_map_.SetAccessInfoParseHelper( + std::make_unique()); + options_.access_info_map = &info_map_; + scc_analyzer_ = std::make_unique(options_); + } + + void SetFile(const FileDescriptor* file) { + if (current_file_ != file) { + split_map_ = cpp::CreateSplitMap(file, options_); + options_.split_map = &split_map_; + current_file_ = file; + } + } + + bool HasProfile(const Descriptor* descriptor) const { + return info_map_.HasProfile(descriptor); + } + + PDProtoAnalysis AnalyzeField(const FieldDescriptor* field) { + PDProtoAnalysis analysis; + + if (info_map_.InProfile(field)) { + if (IsLikelyPresent(field)) { + analysis.presence = PDProtoScale::kLikely; + } else if (IsRarelyPresent(field)) { + analysis.presence = PDProtoScale::kRarely; + } + } + + if (info_map_.InProfile(field) && + info_map_.AccessCount(field, AccessInfoMap::kReadWriteOther) <= + info_map_.GetUnlikelyUsedThreshold()) { + analysis.usage = PDProtoScale::kRarely; + } + + return analysis; + } + + PDProtoOptimization OptimizeField(const FieldDescriptor* field) { + if (IsFieldInlined(field, options_)) { + return PDProtoOptimization::kInline; + } + if (IsLazy(field, options_, scc_analyzer_.get())) { + if (IsLazilyVerifiedLazy(field, options_)) { + return PDProtoOptimization::kUnverifiedLazy; + } + return PDProtoOptimization::kLazy; + } + + if (cpp::ShouldSplit(field, options_)) { + return PDProtoOptimization::kSplit; + } + + return PDProtoOptimization::kNone; + } + + uint64_t UnlikelyUsedThreshold() const { + return info_map_.GetUnlikelyUsedThreshold(); + } + + private: + bool IsLikelyPresent(const FieldDescriptor* field) const { + // This threshold was arbitrarily chosen based on a few macrobenchmark + // results. + constexpr double kHotRatio = 0.90; + + return (info_map_.IsHot(field, AccessInfoMap::kRead, kHotRatio) || + info_map_.IsHot(field, AccessInfoMap::kWrite, kHotRatio)); + } + + bool IsRarelyPresent(const FieldDescriptor* field) const { + // This threshold was arbitrarily chosen based on a few macrobenchmark + // results. Since most cold fields have zero presence count, PDProto + // optimization hasn't been sensitive to the threshold. + constexpr double kColdRatio = 0.005; + + return info_map_.IsCold(field, AccessInfoMap::kRead, kColdRatio) && + info_map_.IsCold(field, AccessInfoMap::kWrite, kColdRatio); + } + + cpp::Options options_; + AccessInfoMap info_map_; + SplitMap split_map_; + std::unique_ptr scc_analyzer_; + const FileDescriptor* current_file_ = nullptr; +}; + +size_t GetLongestName(const DescriptorPool& pool, absl::string_view name, + size_t min_length) { + size_t pos = name.length(); + while (pos > min_length) { + if (name[--pos] == '_') { + if (pool.FindMessageTypeByName(name.substr(0, pos))) { + return pos; + } + } + } + return 0; +} + +const Descriptor* FindMessageTypeByCppName(const DescriptorPool& pool, + absl::string_view name) { + std::string s = absl::StrReplaceAll(name, {{"::", "."}}); + const Descriptor* descriptor = pool.FindMessageTypeByName(s); + if (descriptor) return descriptor; + + size_t min_length = 1; + while (size_t pos = GetLongestName(pool, s, min_length)) { + s[pos] = '.'; + descriptor = pool.FindMessageTypeByName(s); + if (descriptor) return descriptor; + min_length = pos + 1; + } + + ABSL_LOG(WARNING) << "Unknown c++ message name '" << name << "'"; + return nullptr; +} + +std::string TypeName(const FieldDescriptor* descriptor) { + if (descriptor == nullptr) return "UNKNOWN"; + std::string s; + switch (descriptor->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + s = "int32"; + break; + case FieldDescriptor::CPPTYPE_INT64: + s = "int64"; + break; + case FieldDescriptor::CPPTYPE_UINT32: + s = "uint32"; + break; + case FieldDescriptor::CPPTYPE_UINT64: + s = "uint64"; + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + s = "double"; + break; + case FieldDescriptor::CPPTYPE_FLOAT: + s = "float"; + break; + case FieldDescriptor::CPPTYPE_BOOL: + s = "bool"; + break; + case FieldDescriptor::CPPTYPE_ENUM: + s = "enum"; + break; + case FieldDescriptor::CPPTYPE_STRING: + s = "string"; + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + s = descriptor->message_type()->name(); + break; + default: + s = "UNKNOWN"; + break; + } + if (descriptor->is_repeated()) s += "[]"; + return s; +} + +absl::StatusOr AccessInfoFromFile(absl::string_view profile) { + absl::Cord cord; + absl::Status status = GetContents(profile, &cord, true); + if (!status.ok()) { + return status; + } + + AccessInfo access_info_proto; + if (!access_info_proto.ParseFromCord(cord)) { + return absl::DataLossError("Failed to parse AccessInfo"); + } + + return access_info_proto; +} + +std::vector SortMessages( + const AccessInfo& access_info) { + std::vector sorted; + for (const MessageAccessInfo& info : access_info.message()) { + sorted.push_back(&info); + } + std::sort(sorted.begin(), sorted.end(), + [](const MessageAccessInfo* lhs, const MessageAccessInfo* rhs) { + return lhs->name() < rhs->name(); + }); + return sorted; +} + +} // namespace + +absl::Status AnalyzeProfileProtoToText( + std::ostream& stream, absl::string_view proto_profile, + const AnalyzeProfileProtoOptions& options) { + if (options.pool == nullptr) { + return absl::InvalidArgumentError("pool must not be null"); + } + const DescriptorPool& pool = *options.pool; + RE2 regex(options.message_filter.empty() ? ".*" : options.message_filter); + if (!regex.ok()) { + return absl::InvalidArgumentError("Invalid regular expression"); + } + + absl::StatusOr access_info = AccessInfoFromFile(proto_profile); + if (!access_info.ok()) { + return access_info.status(); + } + PDProtoAnalyzer analyzer(*access_info); + + if (options.print_unused_threshold) { + stream << "Unlikely Used Threshold = " << analyzer.UnlikelyUsedThreshold() + << "\n" + << "See http://go/pdlazy for more information\n" + << "-----------------------------------------\n"; + } + + for (const MessageAccessInfo* message : SortMessages(*access_info)) { + if (RE2::PartialMatch(message->name(), regex)) { + if (const Descriptor* descriptor = + FindMessageTypeByCppName(pool, message->name())) { + analyzer.SetFile(descriptor->file()); + if (analyzer.HasProfile(descriptor)) { + bool message_header = false; + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = descriptor->field(i); + PDProtoAnalysis analysis = analyzer.AnalyzeField(field); + PDProtoOptimization optimized = analyzer.OptimizeField(field); + if (options.print_all_fields || options.print_analysis || + optimized != PDProtoOptimization::kNone) { + if (!message_header) { + message_header = true; + stream << "Message " + << absl::StrReplaceAll(descriptor->full_name(), + {{".", "::"}}) + << "\n"; + } + stream << " " << TypeName(field) << " " << field->name() << ":"; + + if (options.print_analysis) { + if (analysis.presence != PDProtoScale::kDefault) { + stream << " " << analysis.presence << "_PRESENT"; + } + if (analysis.usage != PDProtoScale::kDefault) { + stream << " " << analysis.usage << "_USED"; + } + } + if (optimized != PDProtoOptimization::kNone) { + stream << " " << optimized; + } + stream << "\n"; + } + } + } + } + } + } + return absl::OkStatus(); +} + +} // namespace tools +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.h b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.h new file mode 100644 index 0000000000..f80bf5c9eb --- /dev/null +++ b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.h @@ -0,0 +1,42 @@ +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_TOOLS_ANALYZE_PROFILE_PROTO_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_TOOLS_ANALYZE_PROFILE_PROTO_H__ + +#include +#include + +#include "absl/status/status.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace tools { + +struct AnalyzeProfileProtoOptions { + // true to print the 'unlikely used' threshold. + bool print_unused_threshold = true; + + // true to print all fields instead of optimized fields only. + bool print_all_fields = false; + + // true to include presence and usage info instead of only optimization info + bool print_analysis = false; + + // Descriptor pool to use. Must not be null. + const DescriptorPool* pool = nullptr; + + // Regular expression for message name matching, empty to include all. + std::string message_filter; +}; + +absl::Status AnalyzeProfileProtoToText( + std::ostream& stream, absl::string_view proto_profile, + const AnalyzeProfileProtoOptions& options); + +} // namespace tools +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_TOOLS_ANALYZE_PROFILE_PROTO_H__ diff --git a/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_main.cc b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_main.cc new file mode 100644 index 0000000000..4b9035abfe --- /dev/null +++ b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_main.cc @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2023 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include +#include + +#include "base/init_google.h" +#include "google/protobuf/util/globaldb/global_descriptor_database.h" +#include "absl/flags/flag.h" +#include "absl/log/absl_log.h" +#include "absl/status/status.h" +#include "google/protobuf/compiler/cpp/tools/analyze_profile_proto.h" +#include "google/protobuf/descriptor.h" + +ABSL_FLAG(bool, all, false, "Print all fields"); +ABSL_FLAG(bool, analysis, false, "Print field analysis"); +ABSL_FLAG(std::string, message_filter, "", "Regex match for message name"); + +int main(int argc, char* argv[]) { + using google::protobuf::compiler::tools::AnalyzeProfileProtoOptions; + using google::protobuf::compiler::tools::AnalyzeProfileProtoToText; + + InitGoogle(argv[0], &argc, &argv, true); + if (argc < 2) return 1; + + google::protobuf::DescriptorPool pool(google::protobuf::util::globaldb::global()); + AnalyzeProfileProtoOptions options; + options.pool = &pool; + options.print_all_fields = absl::GetFlag(FLAGS_all); + options.print_analysis = absl::GetFlag(FLAGS_analysis); + options.message_filter = absl::GetFlag(FLAGS_message_filter); + absl::Status status = AnalyzeProfileProtoToText(std::cout, argv[1], options); + if (!status.ok()) { + ABSL_LOG(ERROR) << status; + return 2; + } + return 0; +} diff --git a/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_test.cc b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_test.cc new file mode 100644 index 0000000000..04ebbf1c51 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_test.cc @@ -0,0 +1,144 @@ +#include "google/protobuf/compiler/cpp/tools/analyze_profile_proto.h" + +#include +#include + +#include "google/protobuf/testing/file.h" +#include "google/protobuf/testing/file.h" +#include "google/protobuf/testing/path.h" +#include "google/protobuf/compiler/profile.pb.h" +#include "google/protobuf/testing/googletest.h" +#include +#include "absl/log/absl_check.h" +#include "google/protobuf/compiler/cpp/tools/analyze_profile_proto_test.pb.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/test_textproto.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace tools { +namespace { + +std::string AnalyzeToText(const AccessInfo& info, + AnalyzeProfileProtoOptions options) { + std::string filename = file::JoinPath(TestTempDir(), "profile.proto"); + ABSL_CHECK_OK(file::SetBinaryProto(filename, info, true)); + std::stringstream str; + ABSL_CHECK_OK(AnalyzeProfileProtoToText(str, filename, options)); + return str.str(); +} + +TEST(AnalyzeProfileProtoTest, EmptyProfileToText) { + AccessInfo info; + AnalyzeProfileProtoOptions options; + options.pool = DescriptorPool::generated_pool(); + EXPECT_STREQ(AnalyzeToText(info, options).c_str(), + "Unlikely Used Threshold = 0\n" + "See http://go/pdlazy for more information\n" + "-----------------------------------------\n"); +} + +TEST(AnalyzeProfileProtoTest, UnlikelyStringPresence) { + AccessInfo info = ParseTextOrDie(R"pb( + language: "cpp" + message { + name: "google::protobuf::compiler::tools::AnalyzeThis" + count: 100 + field { name: "optional_string" getters_count: 1 } + } + )pb"); + AnalyzeProfileProtoOptions options; + options.print_unused_threshold = false; + options.pool = DescriptorPool::generated_pool(); + EXPECT_STREQ(AnalyzeToText(info, options).c_str(), ""); +} + +TEST(AnalyzeProfileProtoTest, LikelyStringPresence) { + AccessInfo info = ParseTextOrDie(R"pb( + language: "cpp" + message { + name: "google::protobuf::compiler::tools::AnalyzeThis" + count: 100 + field { name: "optional_string" getters_count: 99 } + } + )pb"); + AnalyzeProfileProtoOptions options; + options.print_unused_threshold = false; + options.pool = DescriptorPool::generated_pool(); + EXPECT_STREQ(AnalyzeToText(info, options).c_str(), + "Message google::protobuf::compiler::tools::AnalyzeThis\n" + " string optional_string: INLINE\n"); +} + +TEST(AnalyzeProfileProtoTest, ChildLikelyPresentAndUsed) { + // Note that the logic pics a 50th percentile threshold which we need to + // exceed, making testing slightly awkward + AccessInfo info = ParseTextOrDie(R"pb( + language: "cpp" + message { + name: "google::protobuf::compiler::tools::AnalyzeThis" + count: 100 + field { name: "id" getters_count: 1000 configs_count: 100 } + field { name: "optional_string" getters_count: 100 configs_count: 100 } + field { name: "optional_child" getters_count: 100 configs_count: 102 } + field { name: "repeated_string" getters_count: 100 configs_count: 1 } + field { name: "repeated_child" getters_count: 100 configs_count: 1 } + field { name: "nested" getters_count: 0 configs_count: 1 } + } + )pb"); + AnalyzeProfileProtoOptions options; + options.print_unused_threshold = false; + options.pool = DescriptorPool::generated_pool(); + EXPECT_STREQ(AnalyzeToText(info, options).c_str(), + "Message google::protobuf::compiler::tools::AnalyzeThis\n" + " string optional_string: INLINE\n"); +} + +TEST(AnalyzeProfileProtoTest, ChildLikelyPresentAndRarelyUsed) { + // Note that the logic pics a 50th percentile threshold which we need to + // exceed, making testing slightly awkward + AccessInfo info = ParseTextOrDie(R"pb( + language: "cpp" + message { + name: "google::protobuf::compiler::tools::AnalyzeThis" + count: 100 + field { name: "id" getters_count: 1 configs_count: 100 } + field { name: "optional_string" getters_count: 1 configs_count: 100 } + field { name: "optional_child" getters_count: 100 configs_count: 1 } + field { name: "repeated_string" getters_count: 100 configs_count: 100 } + field { name: "repeated_child" getters_count: 100 configs_count: 100 } + field { name: "nested" getters_count: 1 configs_count: 100 } + } + )pb"); + AnalyzeProfileProtoOptions options; + options.print_unused_threshold = false; + options.pool = DescriptorPool::generated_pool(); + EXPECT_STREQ(AnalyzeToText(info, options).c_str(), + "Message google::protobuf::compiler::tools::AnalyzeThis\n" + " AnalyzeChild optional_child: LAZY\n"); +} + +TEST(AnalyzeProfileProtoTest, NestedCppNameMatchedToPoolName) { + AccessInfo info = ParseTextOrDie(R"pb( + language: "cpp" + message { + name: "google::protobuf::compiler::tools::AnalyzeThis_Nested" + count: 100 + field { name: "id" getters_count: 100 } + field { name: "optional_string" getters_count: 100 } + } + )pb"); + AnalyzeProfileProtoOptions options; + options.print_unused_threshold = false; + options.pool = DescriptorPool::generated_pool(); + EXPECT_STREQ(AnalyzeToText(info, options).c_str(), + "Message google::protobuf::compiler::tools::AnalyzeThis::Nested\n" + " string optional_string: INLINE\n"); +} + +} // namespace +} // namespace tools +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_test.proto b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_test.proto new file mode 100644 index 0000000000..74fe17ca4d --- /dev/null +++ b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto_test.proto @@ -0,0 +1,23 @@ +syntax = "proto2"; + +package google.protobuf.compiler.tools; + +// Non trivial child message +message AnalyzeChild { + optional int32 child_id = 1; + optional AnalyzeChild child = 2; +} + +message AnalyzeThis { + message Nested { + optional int32 nexted_id = 1; + optional string optional_string = 2; + } + + optional int32 id = 1; + optional string optional_string = 2; + repeated string repeated_string = 3; + optional AnalyzeChild optional_child = 4; + repeated AnalyzeChild repeated_child = 5; + optional Nested nested = 6; +} diff --git a/src/google/protobuf/compiler/cpp/unittest.inc b/src/google/protobuf/compiler/cpp/unittest.inc index 169fbb6021..56109d3913 100644 --- a/src/google/protobuf/compiler/cpp/unittest.inc +++ b/src/google/protobuf/compiler/cpp/unittest.inc @@ -926,7 +926,6 @@ TEST(GENERATED_MESSAGE_TEST_NAME, TestOneofSpaceUsed) { #endif // !PROTOBUF_TEST_NO_DESCRIPTORS TEST(GENERATED_MESSAGE_TEST_NAME, FieldConstantValues) { - UNITTEST::TestRequired message; EXPECT_EQ(UNITTEST::TestAllTypes_NestedMessage::kBbFieldNumber, 1); EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalInt32FieldNumber, 1); EXPECT_EQ(UNITTEST::TestAllTypes::kOptionalgroupFieldNumber, 16); diff --git a/src/google/protobuf/compiler/csharp/BUILD.bazel b/src/google/protobuf/compiler/csharp/BUILD.bazel index 414dd0ffd6..a182bc2a30 100644 --- a/src/google/protobuf/compiler/csharp/BUILD.bazel +++ b/src/google/protobuf/compiler/csharp/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( srcs = ["names.cc"], hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/csharp", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -62,7 +62,7 @@ cc_library( "//build_defs:config_msvc": [], "//conditions:default": ["-Wno-overloaded-virtual"], }), - include_prefix = "google/protobuf/compiler/csharp", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/java/BUILD.bazel b/src/google/protobuf/compiler/java/BUILD.bazel index a6e78f0094..8ca67c1bbb 100644 --- a/src/google/protobuf/compiler/java/BUILD.bazel +++ b/src/google/protobuf/compiler/java/BUILD.bazel @@ -10,7 +10,7 @@ cc_library( name = "names", hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/java", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ ":names_internal", @@ -26,15 +26,17 @@ cc_library( "names.cc", ], hdrs = [ + "generator.h", "helpers.h", "name_resolver.h", "names.h", "options.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/java", + strip_include_prefix = "/src", visibility = ["//pkg:__pkg__"], deps = [ + ":java_features_bootstrap", "//src/google/protobuf:descriptor_legacy", "//src/google/protobuf:protobuf_nowkt", "//src/google/protobuf/compiler:code_generator", @@ -42,6 +44,17 @@ cc_library( ], ) +cc_library( + name = "java_features_bootstrap", + srcs = ["java_features.pb.cc"], + hdrs = ["java_features.pb.h"], + strip_include_prefix = "/src", + deps = [ + "//src/google/protobuf:arena", + "//src/google/protobuf:protobuf_nowkt", + ], +) + cc_library( name = "java", srcs = [ @@ -57,7 +70,6 @@ cc_library( "file.cc", "generator.cc", "generator_factory.cc", - "java_features.pb.cc", "kotlin_generator.cc", "map_field.cc", "map_field_lite.cc", @@ -107,12 +119,13 @@ cc_library( "string_field_lite.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/java", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", ], deps = [ + ":java_features_bootstrap", ":names", ":names_internal", "//src/google/protobuf:arena", diff --git a/src/google/protobuf/compiler/java/doc_comment.cc b/src/google/protobuf/compiler/java/doc_comment.cc index dce76a92a3..992cc97100 100644 --- a/src/google/protobuf/compiler/java/doc_comment.cc +++ b/src/google/protobuf/compiler/java/doc_comment.cc @@ -191,6 +191,9 @@ static std::string FirstLineOf(const std::string& value) { static void WriteDebugString(io::Printer* printer, const FieldDescriptor* field, const Options options, const bool kdoc) { std::string field_comment = FirstLineOf(field->DebugString()); + if (options.strip_nonfunctional_codegen) { + field_comment = field->name(); + } if (kdoc) { printer->Print(" * `$def$`\n", "def", EscapeKdoc(field_comment)); } else { diff --git a/src/google/protobuf/compiler/java/file.cc b/src/google/protobuf/compiler/java/file.cc index f116c1781c..5401e8257b 100644 --- a/src/google/protobuf/compiler/java/file.cc +++ b/src/google/protobuf/compiler/java/file.cc @@ -442,6 +442,13 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( FieldDescriptorSet extensions; CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); + if (options_.strip_nonfunctional_codegen) { + // Skip feature extensions, which are a visible (but non-functional) + // deviation between editions and legacy syntax. + absl::erase_if(extensions, [](const FieldDescriptor* field) { + return field->containing_type()->full_name() == "google.protobuf.FeatureSet"; + }); + } if (!extensions.empty()) { // Must construct an ExtensionRegistry containing all existing extensions // and use it to parse the descriptor data again to recognize extensions. @@ -744,6 +751,13 @@ void FileGenerator::GenerateKotlinSiblings( bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor, bool immutable_api) { + // Skip feature imports, which are a visible (but non-functional) deviation + // between editions and legacy syntax. + if (options_.strip_nonfunctional_codegen && + IsKnownFeatureProto(descriptor->name())) { + return false; + } + return true; } diff --git a/src/google/protobuf/compiler/java/generator.cc b/src/google/protobuf/compiler/java/generator.cc index 4ed0029b34..5435bb9e13 100644 --- a/src/google/protobuf/compiler/java/generator.cc +++ b/src/google/protobuf/compiler/java/generator.cc @@ -14,6 +14,8 @@ #include #include +#include "google/protobuf/compiler/code_generator.h" + #include @@ -69,6 +71,8 @@ bool JavaGenerator::Generate(const FileDescriptor* file, file_options.annotate_code = true; } else if (option.first == "annotation_list_file") { file_options.annotation_list_file = option.second; + } else if (option.first == "experimental_strip_nonfunctional_codegen") { + file_options.strip_nonfunctional_codegen = true; } else { *error = absl::StrCat("Unknown generator option: ", option.first); return false; diff --git a/src/google/protobuf/compiler/java/generator.h b/src/google/protobuf/compiler/java/generator.h index 41c00998bc..549d0e5ab6 100644 --- a/src/google/protobuf/compiler/java/generator.h +++ b/src/google/protobuf/compiler/java/generator.h @@ -14,9 +14,13 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ +#include #include +#include #include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/java/java_features.pb.h" +#include "google/protobuf/descriptor.pb.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -43,10 +47,19 @@ class PROTOC_EXPORT JavaGenerator : public CodeGenerator { uint64_t GetSupportedFeatures() const override; + Edition GetMinimumEdition() const override { return Edition::EDITION_PROTO2; } + Edition GetMaximumEdition() const override { return Edition::EDITION_2023; } + + std::vector GetFeatureExtensions() const override { + return {GetExtensionReflection(pb::java)}; + } + void set_opensource_runtime(bool opensource) { opensource_runtime_ = opensource; } + using CodeGenerator::GetResolvedSourceFeatures; + private: bool opensource_runtime_ = PROTO2_IS_OSS; }; diff --git a/src/google/protobuf/compiler/java/helpers.h b/src/google/protobuf/compiler/java/helpers.h index 8390b510b3..8dc75a9ed3 100644 --- a/src/google/protobuf/compiler/java/helpers.h +++ b/src/google/protobuf/compiler/java/helpers.h @@ -16,6 +16,8 @@ #include #include "absl/strings/string_view.h" +#include "google/protobuf/compiler/java/generator.h" +#include "google/protobuf/compiler/java/java_features.pb.h" #include "google/protobuf/compiler/java/names.h" #include "google/protobuf/compiler/java/options.h" #include "google/protobuf/descriptor.h" @@ -349,10 +351,12 @@ inline bool ExposePublicParser(const FileDescriptor* descriptor) { // but in the message and can be queried using additional getters that return // ints. inline bool SupportUnknownEnumValue(const FieldDescriptor* field) { - // TODO: Check Java legacy_enum_field_treated_as_closed feature. - return field->type() != FieldDescriptor::TYPE_ENUM || - FileDescriptorLegacy(field->file()).syntax() == - FileDescriptorLegacy::SYNTAX_PROTO3; + if (JavaGenerator::GetResolvedSourceFeatures(*field) + .GetExtension(pb::java) + .legacy_closed_enum()) { + return false; + } + return field->enum_type() != nullptr && !field->enum_type()->is_closed(); } // Check whether a message has repeated fields. @@ -375,7 +379,14 @@ inline bool IsWrappersProtoFile(const FileDescriptor* descriptor) { } inline bool CheckUtf8(const FieldDescriptor* descriptor) { - return descriptor->requires_utf8_validation() || + if (JavaGenerator::GetResolvedSourceFeatures(*descriptor) + .GetExtension(pb::java) + .utf8_validation() == pb::JavaFeatures::VERIFY) { + return true; + } + return JavaGenerator::GetResolvedSourceFeatures(*descriptor) + .utf8_validation() == FeatureSet::VERIFY || + // For legacy syntax. This is not allowed under Editions. descriptor->file()->options().java_string_check_utf8(); } diff --git a/src/google/protobuf/compiler/java/java_features.pb.cc b/src/google/protobuf/compiler/java/java_features.pb.cc index 99ab9eb8d0..309375292d 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.cc +++ b/src/google/protobuf/compiler/java/java_features.pb.cc @@ -46,31 +46,33 @@ static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fjava_2 static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto[1]; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _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(::pb::JavaFeatures, _impl_.legacy_closed_enum_), - PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.utf8_validation_), - 0, - 1, +const ::uint32_t + TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _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(::pb::JavaFeatures, _impl_.legacy_closed_enum_), + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.utf8_validation_), + 0, + 1, }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, 10, -1, sizeof(::pb::JavaFeatures)}, }; static const ::_pb::Message* const file_default_instances[] = { &::pb::_JavaFeatures_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n1google/protobuf/compiler/java/java_fea" "tures.proto\022\002pb\032 google/protobuf/descrip" "tor.proto\"\352\001\n\014JavaFeatures\022>\n\022legacy_clo" @@ -194,6 +196,16 @@ inline void JavaFeatures::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +JavaFeatures::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + JavaFeatures::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void JavaFeatures::Clear() { // @@protoc_insertion_point(message_clear_start:pb.JavaFeatures) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -310,13 +322,6 @@ const ::_pbi::TcParseTable<1, 2, 1, 0, 2> JavaFeatures::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData JavaFeatures::_class_data_ = { - JavaFeatures::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* JavaFeatures::GetClassData() const { - return &_class_data_; -} void JavaFeatures::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/compiler/java/java_features.pb.h b/src/google/protobuf/compiler/java/java_features.pb.h index b0871acf90..f5f8b7d641 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.h +++ b/src/google/protobuf/compiler/java/java_features.pb.h @@ -201,7 +201,7 @@ class PROTOC_EXPORT JavaFeatures final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -224,11 +224,9 @@ class PROTOC_EXPORT JavaFeatures final : protected: explicit JavaFeatures(::google::protobuf::Arena* arena); JavaFeatures(::google::protobuf::Arena* arena, const JavaFeatures& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/compiler/java/kotlin_generator.cc b/src/google/protobuf/compiler/java/kotlin_generator.cc index 881ef018a5..5cf3482edc 100644 --- a/src/google/protobuf/compiler/java/kotlin_generator.cc +++ b/src/google/protobuf/compiler/java/kotlin_generator.cc @@ -54,6 +54,8 @@ bool KotlinGenerator::Generate(const FileDescriptor* file, file_options.annotate_code = true; } else if (option.first == "annotation_list_file") { file_options.annotation_list_file = option.second; + } else if (option.first == "experimental_strip_nonfunctional_codegen") { + file_options.strip_nonfunctional_codegen = true; } else { *error = absl::StrCat("Unknown generator option: ", option.first); return false; diff --git a/src/google/protobuf/compiler/java/kotlin_generator.h b/src/google/protobuf/compiler/java/kotlin_generator.h index 8323f21baa..afc4085646 100644 --- a/src/google/protobuf/compiler/java/kotlin_generator.h +++ b/src/google/protobuf/compiler/java/kotlin_generator.h @@ -13,6 +13,8 @@ #include #include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/java/java_features.pb.h" +#include "google/protobuf/descriptor.pb.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -38,6 +40,15 @@ class PROTOC_EXPORT KotlinGenerator : public CodeGenerator { GeneratorContext* context, std::string* error) const override; uint64_t GetSupportedFeatures() const override; + + Edition GetMinimumEdition() const override { return Edition::EDITION_PROTO2; } + Edition GetMaximumEdition() const override { return Edition::EDITION_2023; } + + std::vector GetFeatureExtensions() const override { + return {GetExtensionReflection(pb::java)}; + } + + using CodeGenerator::GetResolvedSourceFeatures; }; } // namespace java diff --git a/src/google/protobuf/compiler/java/message_lite.cc b/src/google/protobuf/compiler/java/message_lite.cc index d207aa8696..587f2ccf91 100644 --- a/src/google/protobuf/compiler/java/message_lite.cc +++ b/src/google/protobuf/compiler/java/message_lite.cc @@ -487,14 +487,18 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuildMessageInfo( int flags = 0; if (FileDescriptorLegacy(descriptor_->file()).syntax() == FileDescriptorLegacy::Syntax::SYNTAX_PROTO2) { - flags |= 0x1; + if (!context_->options().strip_nonfunctional_codegen) { + flags |= 0x1; + } } if (descriptor_->options().message_set_wire_format()) { flags |= 0x2; } if (FileDescriptorLegacy(descriptor_->file()).syntax() == FileDescriptorLegacy::Syntax::SYNTAX_EDITIONS) { - flags |= 0x4; + if (!context_->options().strip_nonfunctional_codegen) { + flags |= 0x4; + } } WriteIntToUtf16CharSequence(flags, &chars); diff --git a/src/google/protobuf/compiler/java/message_serialization_unittest.cc b/src/google/protobuf/compiler/java/message_serialization_unittest.cc index 997a2d1fb2..51d66a2efc 100644 --- a/src/google/protobuf/compiler/java/message_serialization_unittest.cc +++ b/src/google/protobuf/compiler/java/message_serialization_unittest.cc @@ -47,10 +47,11 @@ int CompileJavaProto(std::string proto_file_name) { "protoc", proto_path.c_str(), java_out.c_str(), + "--experimental_editions", proto_file_name.c_str(), }; - return cli.Run(4, argv); + return cli.Run(5, argv); } TEST(MessageSerializationTest, CollapseAdjacentExtensionRanges) { diff --git a/src/google/protobuf/compiler/java/message_serialization_unittest.proto b/src/google/protobuf/compiler/java/message_serialization_unittest.proto index e426a1b68e..acd3848f1f 100644 --- a/src/google/protobuf/compiler/java/message_serialization_unittest.proto +++ b/src/google/protobuf/compiler/java/message_serialization_unittest.proto @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; @@ -18,15 +18,15 @@ message TestMessageWithManyExtensionRanges { // First extension range: ends at field number 3 (exclusive) extensions 1 to 2; - optional int32 foo = 3; - optional int32 bar = 5; + int32 foo = 3; + int32 bar = 5; // Second extension range: ends at field number 13 (exclusive) extensions 6; extensions 8; extensions 10 to 12; - optional int32 baz = 23; + int32 baz = 23; // Third extension range: ends at field number 43 (exclusive) extensions 42; diff --git a/src/google/protobuf/compiler/java/options.h b/src/google/protobuf/compiler/java/options.h index af43d4f024..f10b699c68 100644 --- a/src/google/protobuf/compiler/java/options.h +++ b/src/google/protobuf/compiler/java/options.h @@ -24,7 +24,8 @@ struct Options { generate_mutable_code(false), generate_shared_code(false), enforce_lite(false), - annotate_code(false) { + annotate_code(false), + strip_nonfunctional_codegen(false) { } bool generate_immutable_code; @@ -43,6 +44,8 @@ struct Options { // Name of a file where we will write a list of generated file names, one // per line. std::string output_list_file; + // If true, strip out nonfunctional codegen. + bool strip_nonfunctional_codegen; }; } // namespace java diff --git a/src/google/protobuf/compiler/java/plugin_unittest.cc b/src/google/protobuf/compiler/java/plugin_unittest.cc index eabe1196f0..393f94d390 100644 --- a/src/google/protobuf/compiler/java/plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/plugin_unittest.cc @@ -52,6 +52,13 @@ class TestGenerator : public CodeGenerator { io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } + + uint64_t GetSupportedFeatures() const override { + return CodeGenerator::Feature::FEATURE_SUPPORTS_EDITIONS; + } + + Edition GetMinimumEdition() const override { return Edition::EDITION_PROTO2; } + Edition GetMaximumEdition() const override { return Edition::EDITION_2023; } }; // This test verifies that all the expected insertion points exist. It does @@ -60,14 +67,17 @@ class TestGenerator : public CodeGenerator { TEST(JavaPluginTest, PluginTest) { ABSL_CHECK_OK( File::SetContents(absl::StrCat(TestTempDir(), "/test.proto"), - "syntax = \"proto2\";\n" + "edition = \"2023\";\n" "package foo;\n" "option java_package = \"\";\n" "option java_outer_classname = \"Test\";\n" "message Bar {\n" " message Baz {}\n" "}\n" - "enum Qux { BLAH = 1; }\n", + "enum Qux {\n" + " option features.enum_type = CLOSED;\n" + " BLAH = 1;\n" + "}\n", true)); CommandLineInterface cli; @@ -82,10 +92,11 @@ TEST(JavaPluginTest, PluginTest) { std::string java_out = absl::StrCat("--java_out=", TestTempDir()); std::string test_out = absl::StrCat("--test_out=", TestTempDir()); - const char* argv[] = {"protoc", proto_path.c_str(), java_out.c_str(), - test_out.c_str(), "test.proto"}; + const char* argv[] = { + "protoc", proto_path.c_str(), java_out.c_str(), + test_out.c_str(), "--experimental_editions", "test.proto"}; - EXPECT_EQ(0, cli.Run(5, argv)); + EXPECT_EQ(0, cli.Run(6, argv)); // Loop over the lines of the generated code and verify that we find what we // expect diff --git a/src/google/protobuf/compiler/java/shared_code_generator.cc b/src/google/protobuf/compiler/java/shared_code_generator.cc index c8c584e9b7..3def00c69b 100644 --- a/src/google/protobuf/compiler/java/shared_code_generator.cc +++ b/src/google/protobuf/compiler/java/shared_code_generator.cc @@ -113,6 +113,11 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { // code size limits (error "code to large"). String literals are apparently // embedded raw, which is what we want. FileDescriptorProto file_proto = StripSourceRetentionOptions(*file_); + // Skip serialized file descriptor proto, which contain non-functional + // deviation between editions and legacy syntax (e.g. syntax, features) + if (options_.strip_nonfunctional_codegen) { + file_proto.Clear(); + } std::string file_data; file_proto.SerializeToString(&file_data); diff --git a/src/google/protobuf/compiler/main_no_generators.cc b/src/google/protobuf/compiler/main_no_generators.cc new file mode 100644 index 0000000000..83a44e8b4c --- /dev/null +++ b/src/google/protobuf/compiler/main_no_generators.cc @@ -0,0 +1,36 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "google/protobuf/compiler/command_line_interface.h" + +#include "absl/log/initialize.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { + +// This is a version of protoc that has no built-in code generators. +// See go/protobuf-toolchain-protoc +int ProtocMain(int argc, char* argv[]) { + absl::InitializeLog(); + + CommandLineInterface cli; + cli.AllowPlugins("protoc-"); + + return cli.Run(argc, argv); +} + +} // namespace compiler +} // namespace protobuf +} // namespace google + +int main(int argc, char* argv[]) { + return google::protobuf::compiler::ProtocMain(argc, argv); +} diff --git a/src/google/protobuf/compiler/objectivec/BUILD.bazel b/src/google/protobuf/compiler/objectivec/BUILD.bazel index 5ab3381afa..a3a6fcfec0 100644 --- a/src/google/protobuf/compiler/objectivec/BUILD.bazel +++ b/src/google/protobuf/compiler/objectivec/BUILD.bazel @@ -10,7 +10,7 @@ cc_library( name = "names", hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/objectivec", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ ":names_internal", @@ -27,7 +27,7 @@ cc_library( "nsobject_methods.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/objectivec", + strip_include_prefix = "/src", visibility = ["//pkg:__pkg__"], deps = [ ":line_consumer", @@ -43,7 +43,7 @@ cc_library( srcs = ["line_consumer.cc"], hdrs = ["line_consumer.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/objectivec", + strip_include_prefix = "/src", visibility = ["//pkg:__pkg__"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -87,7 +87,7 @@ cc_library( "text_format_decode_data.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/objectivec", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/php/BUILD.bazel b/src/google/protobuf/compiler/php/BUILD.bazel index f814a03a74..2a9746d808 100644 --- a/src/google/protobuf/compiler/php/BUILD.bazel +++ b/src/google/protobuf/compiler/php/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( srcs = ["names.cc"], hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/php", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -25,7 +25,7 @@ cc_library( srcs = ["php_generator.cc"], hdrs = ["php_generator.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/php", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index 471caa7914..166e1c0851 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -94,18 +94,15 @@ bool GenerateCode(const CodeGeneratorRequest& request, CodeGeneratorResponse* response, std::string* error_msg) { DescriptorPool pool; - if (generator.GetSupportedFeatures() & - CodeGenerator::FEATURE_SUPPORTS_EDITIONS) { - // Initialize feature set default mapping. - absl::StatusOr defaults = - generator.BuildFeatureSetDefaults(); - if (!defaults.ok()) { - *error_msg = absl::StrCat("error generating feature defaults: ", - defaults.status().message()); - return false; - } - pool.SetFeatureSetDefaults(*defaults); + // Initialize feature set default mapping. + absl::StatusOr defaults = + generator.BuildFeatureSetDefaults(); + if (!defaults.ok()) { + *error_msg = absl::StrCat("error generating feature defaults: ", + defaults.status().message()); + return false; } + pool.SetFeatureSetDefaults(*defaults); for (int i = 0; i < request.proto_file_size(); i++) { const FileDescriptor* file = pool.BuildFile(request.proto_file(i)); diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 684bdd31d7..06e403cc6e 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -130,76 +130,77 @@ static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1]; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_.major_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_.minor_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_.patch_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_.suffix_), - 1, - 2, - 3, - 0, - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.file_to_generate_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.parameter_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.proto_file_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.source_file_descriptors_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.compiler_version_), - ~0u, - 0, - ~0u, - ~0u, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_.insertion_point_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_.content_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_.generated_code_info_), - 0, - 1, - 2, - 3, - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.error_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.supported_features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.file_), - 0, - 1, - ~0u, +const ::uint32_t + TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_.major_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_.minor_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_.patch_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _impl_.suffix_), + 1, + 2, + 3, + 0, + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.file_to_generate_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.parameter_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.proto_file_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.source_file_descriptors_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _impl_.compiler_version_), + ~0u, + 0, + ~0u, + ~0u, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_.insertion_point_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_.content_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _impl_.generated_code_info_), + 0, + 1, + 2, + 3, + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.error_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.supported_features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.file_), + 0, + 1, + ~0u, }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, 12, -1, sizeof(::google::protobuf::compiler::Version)}, {16, 29, -1, sizeof(::google::protobuf::compiler::CodeGeneratorRequest)}, {34, 46, -1, sizeof(::google::protobuf::compiler::CodeGeneratorResponse_File)}, @@ -212,7 +213,8 @@ static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::compiler::_CodeGeneratorResponse_File_default_instance_._instance, &::google::protobuf::compiler::_CodeGeneratorResponse_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n%google/protobuf/compiler/plugin.proto\022" "\030google.protobuf.compiler\032 google/protob" "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030" @@ -379,6 +381,16 @@ inline void Version::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Version::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Version::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Version::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -541,13 +553,6 @@ const ::_pbi::TcParseTable<2, 4, 0, 47, 2> Version::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Version::_class_data_ = { - Version::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Version::GetClassData() const { - return &_class_data_; -} void Version::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -693,6 +698,16 @@ inline void CodeGeneratorRequest::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +CodeGeneratorRequest::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + CodeGeneratorRequest::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void CodeGeneratorRequest::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -885,13 +900,6 @@ const ::_pbi::TcParseTable<3, 5, 3, 79, 2> CodeGeneratorRequest::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData CodeGeneratorRequest::_class_data_ = { - CodeGeneratorRequest::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* CodeGeneratorRequest::GetClassData() const { - return &_class_data_; -} void CodeGeneratorRequest::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1041,6 +1049,16 @@ inline void CodeGeneratorResponse_File::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +CodeGeneratorResponse_File::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + CodeGeneratorResponse_File::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void CodeGeneratorResponse_File::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1214,13 +1232,6 @@ const ::_pbi::TcParseTable<2, 4, 1, 86, 2> CodeGeneratorResponse_File::_table_ = return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData CodeGeneratorResponse_File::_class_data_ = { - CodeGeneratorResponse_File::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* CodeGeneratorResponse_File::GetClassData() const { - return &_class_data_; -} void CodeGeneratorResponse_File::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1343,6 +1354,16 @@ inline void CodeGeneratorResponse::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +CodeGeneratorResponse::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + CodeGeneratorResponse::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void CodeGeneratorResponse::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1485,13 +1506,6 @@ const ::_pbi::TcParseTable<2, 3, 1, 60, 2> CodeGeneratorResponse::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData CodeGeneratorResponse::_class_data_ = { - CodeGeneratorResponse::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* CodeGeneratorResponse::GetClassData() const { - return &_class_data_; -} void CodeGeneratorResponse::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 574c172542..8d47638d3d 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -218,7 +218,7 @@ class PROTOC_EXPORT Version final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -241,11 +241,9 @@ class PROTOC_EXPORT Version final : protected: explicit Version(::google::protobuf::Arena* arena); Version(::google::protobuf::Arena* arena, const Version& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -440,7 +438,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -463,11 +461,9 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : protected: explicit CodeGeneratorResponse_File(::google::protobuf::Arena* arena); CodeGeneratorResponse_File(::google::protobuf::Arena* arena, const CodeGeneratorResponse_File& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -678,7 +674,7 @@ class PROTOC_EXPORT CodeGeneratorResponse final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -701,11 +697,9 @@ class PROTOC_EXPORT CodeGeneratorResponse final : protected: explicit CodeGeneratorResponse(::google::protobuf::Arena* arena); CodeGeneratorResponse(::google::protobuf::Arena* arena, const CodeGeneratorResponse& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -917,7 +911,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -940,11 +934,9 @@ class PROTOC_EXPORT CodeGeneratorRequest final : protected: explicit CodeGeneratorRequest(::google::protobuf::Arena* arena); CodeGeneratorRequest(::google::protobuf::Arena* arena, const CodeGeneratorRequest& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1606,11 +1598,11 @@ inline void CodeGeneratorRequest::set_allocated_compiler_version(::google::proto ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::compiler::Version*>(_impl_.compiler_version_); + delete (_impl_.compiler_version_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::compiler::Version*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } diff --git a/src/google/protobuf/compiler/python/BUILD.bazel b/src/google/protobuf/compiler/python/BUILD.bazel index 64b5808cb6..e9501f2b56 100644 --- a/src/google/protobuf/compiler/python/BUILD.bazel +++ b/src/google/protobuf/compiler/python/BUILD.bazel @@ -19,7 +19,7 @@ cc_library( "pyi_generator.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/python", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/python/generator.cc b/src/google/protobuf/compiler/python/generator.cc index f3cce736d6..3f3410e3cd 100644 --- a/src/google/protobuf/compiler/python/generator.cc +++ b/src/google/protobuf/compiler/python/generator.cc @@ -22,6 +22,8 @@ #include "google/protobuf/compiler/python/generator.h" #include +#include +#include #include #include #include @@ -31,14 +33,17 @@ #include "absl/container/flat_hash_map.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" +#include "absl/memory/memory.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" +#include "absl/strings/str_join.h" #include "absl/strings/str_replace.h" #include "absl/strings/string_view.h" #include "absl/strings/strip.h" #include "absl/strings/substitute.h" +#include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/python/helpers.h" #include "google/protobuf/compiler/python/pyi_generator.h" #include "google/protobuf/compiler/retention.h" @@ -46,9 +51,12 @@ #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/descriptor_legacy.h" +#include "google/protobuf/descriptor_visitor.h" +#include "google/protobuf/dynamic_message.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/io/strtod.h" #include "google/protobuf/io/zero_copy_stream.h" +#include "google/protobuf/message.h" namespace google { namespace protobuf { @@ -152,21 +160,6 @@ std::string StringifyDefaultValue(const FieldDescriptor& field) { return ""; } -std::string StringifySyntax(FileDescriptorLegacy::Syntax syntax) { - switch (syntax) { - case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2: - return "proto2"; - case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3: - return "proto3"; - case FileDescriptorLegacy::Syntax::SYNTAX_UNKNOWN: - default: - ABSL_LOG(FATAL) - << "Unsupported syntax; this generator only supports proto2 " - "and proto3 syntax."; - return ""; - } -} - } // namespace Generator::Generator() : file_(nullptr) {} @@ -194,6 +187,8 @@ GeneratorOptions Generator::ParseParameter(absl::string_view parameter, options.generate_pyi = true; } else if (option.first == "annotate_code") { options.annotate_pyi = true; + } else if (option.first == "experimental_strip_nonfunctional_codegen") { + options.strip_nonfunctional_codegen = true; } else { *error = absl::StrCat("Unknown generator option: ", option.first); } @@ -211,8 +206,15 @@ bool Generator::Generate(const FileDescriptor* file, // 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)) { + std::vector pyi_options; + if (options.annotate_pyi) { + pyi_options.push_back("annotate_code"); + } + if (options.strip_nonfunctional_codegen) { + pyi_options.push_back("experimental_strip_nonfunctional_codegen"); + } + if (!pyi_generator.Generate(file, absl::StrJoin(pyi_options, ","), context, + error)) { return false; } } @@ -286,6 +288,7 @@ bool Generator::Generate(const FileDescriptor* file, PrintAllEnumsInFile(); PrintMessageDescriptors(); FixForeignFieldsInDescriptors(); + PrintResolvedFeatures(); printer_->Outdent(); printer_->Print("else:\n"); printer_->Indent(); @@ -417,13 +420,119 @@ void Generator::PrintImports() const { printer_->Print("\n"); } +template +std::string Generator::GetResolvedFeatures( + const DescriptorT& descriptor) const { + if (!GeneratingDescriptorProto()) { + // Everything but descriptor.proto can handle proper feature resolution. + return "None"; + } + + // Load the resolved features from our pool. + const Descriptor* feature_set = file_->pool()->FindMessageTypeByName( + FeatureSet::GetDescriptor()->full_name()); + auto message_factory = absl::make_unique(); + auto features = + absl::WrapUnique(message_factory->GetPrototype(feature_set)->New()); + features->ParseFromString( + GetResolvedSourceFeatures(descriptor).SerializeAsString()); + + // Collect all of the resolved features. + std::vector feature_args; + const Reflection* reflection = features->GetReflection(); + std::vector fields; + reflection->ListFields(*features, &fields); + for (const auto* field : fields) { + // Assume these are all enums. If we add non-enum global features or any + // python-specific features, we will need to come back and improve this + // logic. + ABSL_CHECK(field->enum_type() != nullptr) + << "Unexpected non-enum field found!"; + if (field->options().retention() == FieldOptions::RETENTION_SOURCE) { + // Skip any source-retention features. + continue; + } + const EnumDescriptor* enm = field->enum_type(); + const EnumValueDescriptor* value = + enm->FindValueByNumber(reflection->GetEnumValue(*features, field)); + + feature_args.emplace_back(absl::StrCat( + field->name(), "=", + absl::StrFormat("%s.values_by_name[\"%s\"].number", + ModuleLevelDescriptorName(*enm), value->name()))); + } + return absl::StrCat("_ResolvedFeatures(", absl::StrJoin(feature_args, ","), + ")"); +} + +void Generator::PrintResolvedFeatures() const { + // Since features are used during the descriptor build, it's impossible to do + // feature resolution at the normal point for descriptor.proto. Instead, we do + // feature resolution here in the generator, and embed a custom object on all + // of the generated descriptors. This object should act like any other + // FeatureSet message on normal descriptors, but will never have to be + // resolved by the python runtime. + ABSL_CHECK(GeneratingDescriptorProto()); + printer_->Emit({{"resolved_features", GetResolvedFeatures(*file_)}, + {"descriptor_name", kDescriptorKey}}, + R"py( + class _ResolvedFeatures: + def __init__(self, features = None, **kwargs): + if features: + for k, v in features.FIELDS.items(): + setattr(self, k, getattr(features, k)) + else: + for k, v in kwargs.items(): + setattr(self, k, v) + $descriptor_name$._features = $resolved_features$ + )py"); + +#define MAKE_NESTED(desc, CPP_FIELD, PY_FIELD) \ + [&] { \ + for (int i = 0; i < desc.CPP_FIELD##_count(); ++i) { \ + printer_->Emit( \ + {{"resolved_subfeatures", GetResolvedFeatures(*desc.CPP_FIELD(i))}, \ + {"index", absl::StrCat(i)}, \ + {"field", PY_FIELD}}, \ + "$descriptor_name$.$field$[$index$]._features = " \ + "$resolved_subfeatures$\n"); \ + } \ + } + + internal::VisitDescriptors(*file_, [&](const Descriptor& msg) { + printer_->Emit( + {{"resolved_features", GetResolvedFeatures(msg)}, + {"descriptor_name", ModuleLevelDescriptorName(msg)}, + {"field_features", MAKE_NESTED(msg, field, "fields")}, + {"oneof_features", MAKE_NESTED(msg, oneof_decl, "oneofs")}, + {"ext_features", MAKE_NESTED(msg, extension, "extensions")}}, + R"py( + $descriptor_name$._features = $resolved_features$ + $field_features$ + $oneof_features$ + $ext_features$ + )py"); + }); + internal::VisitDescriptors(*file_, [&](const EnumDescriptor& enm) { + printer_->Emit({{"resolved_features", GetResolvedFeatures(enm)}, + {"descriptor_name", ModuleLevelDescriptorName(enm)}, + {"value_features", MAKE_NESTED(enm, value, "values")}}, + R"py( + $descriptor_name$._features = $resolved_features$ + $value_features$ + )py"); + }); +#undef MAKE_NESTED +} + // Prints the single file descriptor for this file. void Generator::PrintFileDescriptor() const { absl::flat_hash_map m; m["descriptor_name"] = kDescriptorKey; m["name"] = file_->name(); m["package"] = file_->package(); - m["syntax"] = StringifySyntax(FileDescriptorLegacy(file_).syntax()); + m["syntax"] = std::string( + FileDescriptorLegacy::SyntaxName(FileDescriptorLegacy(file_).syntax())); m["options"] = OptionsValue( StripLocalSourceRetentionOptions(*file_).SerializeAsString()); m["serialized_descriptor"] = absl::CHexEscape(file_descriptor_serialized_); @@ -677,8 +786,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { "options_value", OptionsValue(options_string), "extendable", message_descriptor.extension_range_count() > 0 ? "True" : "False", "syntax", - StringifySyntax( - FileDescriptorLegacy(message_descriptor.file()).syntax())); + FileDescriptorLegacy::SyntaxName(FileDescriptorLegacy(file_).syntax())); printer_->Print(",\n"); // Extension ranges @@ -1167,7 +1275,7 @@ void Generator::PrintSerializedPbInterval( const DescriptorProtoT& descriptor_proto, absl::string_view name) const { std::string sp; descriptor_proto.SerializeToString(&sp); - int offset = file_descriptor_serialized_.find(sp); + size_t offset = file_descriptor_serialized_.find(sp); ABSL_CHECK_GE(offset, 0); printer_->Print( @@ -1177,26 +1285,34 @@ void Generator::PrintSerializedPbInterval( absl::StrCat(offset + sp.size())); } -namespace { -void PrintDescriptorOptionsFixingCode(absl::string_view descriptor, - absl::string_view options, - io::Printer* printer) { +template +bool Generator::PrintDescriptorOptionsFixingCode( + const DescriptorT& descriptor, absl::string_view descriptor_str) const { + std::string options = OptionsValue( + StripLocalSourceRetentionOptions(descriptor).SerializeAsString()); + // Reset the _options to None thus DescriptorBase.GetOptions() can // parse _options again after extensions are registered. - size_t dot_pos = descriptor.find('.'); + size_t dot_pos = descriptor_str.find('.'); std::string descriptor_name; if (dot_pos == std::string::npos) { - descriptor_name = absl::StrCat("_globals['", descriptor, "']"); + descriptor_name = absl::StrCat("_globals['", descriptor_str, "']"); } else { - descriptor_name = absl::StrCat("_globals['", descriptor.substr(0, dot_pos), - "']", descriptor.substr(dot_pos)); + descriptor_name = + absl::StrCat("_globals['", descriptor_str.substr(0, dot_pos), "']", + descriptor_str.substr(dot_pos)); } - printer->Print( + + if (options == "None") { + return false; + } + + printer_->Print( "$descriptor_name$._options = None\n" "$descriptor_name$._serialized_options = $serialized_value$\n", "descriptor_name", descriptor_name, "serialized_value", options); + return true; } -} // namespace // Generates the start and end offsets for each entity in the serialized file // descriptor. The file argument must exactly match what was serialized into @@ -1246,11 +1362,7 @@ void Generator::SetMessagePbInterval(const DescriptorProto& message_proto, // Prints expressions that set the options field of all descriptors. void Generator::FixAllDescriptorOptions() const { // Prints an expression that sets the file descriptor's options. - std::string file_options = OptionsValue( - StripLocalSourceRetentionOptions(*file_).SerializeAsString()); - if (file_options != "None") { - PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_); - } else { + if (!PrintDescriptorOptionsFixingCode(*file_, kDescriptorKey)) { printer_->Print("DESCRIPTOR._options = None\n"); } // Prints expressions that set the options for all top level enums. @@ -1275,35 +1387,23 @@ void Generator::FixAllDescriptorOptions() const { } void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const { - std::string oneof_options = - OptionsValue(StripLocalSourceRetentionOptions(oneof).SerializeAsString()); - if (oneof_options != "None") { - std::string oneof_name = absl::Substitute( - "$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()), - "oneofs_by_name", oneof.name()); - PrintDescriptorOptionsFixingCode(oneof_name, oneof_options, printer_); - } + std::string oneof_name = absl::Substitute( + "$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()), + "oneofs_by_name", oneof.name()); + PrintDescriptorOptionsFixingCode(oneof, oneof_name); } // Prints expressions that set the options for an enum descriptor and its // value descriptors. void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { std::string descriptor_name = ModuleLevelDescriptorName(enum_descriptor); - std::string enum_options = OptionsValue( - StripLocalSourceRetentionOptions(enum_descriptor).SerializeAsString()); - if (enum_options != "None") { - PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_); - } + PrintDescriptorOptionsFixingCode(enum_descriptor, descriptor_name); for (int i = 0; i < enum_descriptor.value_count(); ++i) { const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i); - std::string value_options = OptionsValue( - StripLocalSourceRetentionOptions(value_descriptor).SerializeAsString()); - if (value_options != "None") { - PrintDescriptorOptionsFixingCode( - absl::StrFormat("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), - value_descriptor.name().c_str()), - value_options, printer_); - } + PrintDescriptorOptionsFixingCode( + value_descriptor, + absl::StrFormat("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), + value_descriptor.name().c_str())); } } @@ -1313,46 +1413,33 @@ void Generator::FixOptionsForService( const ServiceDescriptor& service_descriptor) const { std::string descriptor_name = ModuleLevelServiceDescriptorName(service_descriptor); - std::string service_options = OptionsValue( - StripLocalSourceRetentionOptions(service_descriptor).SerializeAsString()); - if (service_options != "None") { - PrintDescriptorOptionsFixingCode(descriptor_name, service_options, - printer_); - } + PrintDescriptorOptionsFixingCode(service_descriptor, descriptor_name); for (int i = 0; i < service_descriptor.method_count(); ++i) { const MethodDescriptor* method = service_descriptor.method(i); - std::string method_options = OptionsValue( - StripLocalSourceRetentionOptions(*method).SerializeAsString()); - if (method_options != "None") { - std::string method_name = absl::StrCat( - descriptor_name, ".methods_by_name['", method->name(), "']"); - PrintDescriptorOptionsFixingCode(method_name, method_options, printer_); - } + PrintDescriptorOptionsFixingCode( + *method, absl::StrCat(descriptor_name, ".methods_by_name['", + method->name(), "']")); } } // Prints expressions that set the options for field descriptors (including // extensions). void Generator::FixOptionsForField(const FieldDescriptor& field) const { - std::string field_options = - OptionsValue(StripLocalSourceRetentionOptions(field).SerializeAsString()); - if (field_options != "None") { - std::string field_name; - if (field.is_extension()) { - if (field.extension_scope() == nullptr) { - // Top level extensions. - field_name = field.name(); - } else { - field_name = FieldReferencingExpression(field.extension_scope(), field, - "extensions_by_name"); - } + std::string field_name; + if (field.is_extension()) { + if (field.extension_scope() == nullptr) { + // Top level extensions. + field_name = field.name(); } else { - field_name = FieldReferencingExpression(field.containing_type(), field, - "fields_by_name"); + field_name = FieldReferencingExpression(field.extension_scope(), field, + "extensions_by_name"); } - PrintDescriptorOptionsFixingCode(field_name, field_options, printer_); + } else { + field_name = FieldReferencingExpression(field.containing_type(), field, + "fields_by_name"); } + PrintDescriptorOptionsFixingCode(field, field_name); } // Prints expressions that set the options for a message and all its inner @@ -1381,13 +1468,8 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { FixOptionsForField(field); } // Message option for this message. - std::string message_options = OptionsValue( - StripLocalSourceRetentionOptions(descriptor).SerializeAsString()); - if (message_options != "None") { - std::string descriptor_name = ModuleLevelDescriptorName(descriptor); - PrintDescriptorOptionsFixingCode(descriptor_name, message_options, - printer_); - } + PrintDescriptorOptionsFixingCode(descriptor, + ModuleLevelDescriptorName(descriptor)); } // If a dependency forwards other files through public dependencies, let's diff --git a/src/google/protobuf/compiler/python/generator.h b/src/google/protobuf/compiler/python/generator.h index 2c73140d9c..c5beeeea35 100644 --- a/src/google/protobuf/compiler/python/generator.h +++ b/src/google/protobuf/compiler/python/generator.h @@ -12,6 +12,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ +#include #include #include @@ -49,6 +50,7 @@ struct GeneratorOptions { bool generate_pyi = false; bool annotate_pyi = false; bool bootstrap = false; + bool strip_nonfunctional_codegen = false; }; class PROTOC_EXPORT Generator : public CodeGenerator { @@ -73,6 +75,9 @@ class PROTOC_EXPORT Generator : public CodeGenerator { GeneratorOptions ParseParameter(absl::string_view parameter, std::string* error) const; void PrintImports() const; + template + std::string GetResolvedFeatures(const DescriptorT& descriptor) const; + void PrintResolvedFeatures() const; void PrintFileDescriptor() const; void PrintAllEnumsInFile() const; void PrintNestedEnums(const Descriptor& descriptor) const; @@ -141,6 +146,10 @@ class PROTOC_EXPORT Generator : public CodeGenerator { void PrintSerializedPbInterval(const DescriptorProtoT& descriptor_proto, absl::string_view name) const; + template + bool PrintDescriptorOptionsFixingCode(const DescriptorT& descriptor, + absl::string_view descriptor_str) const; + void FixAllDescriptorOptions() const; void FixOptionsForField(const FieldDescriptor& field) const; void FixOptionsForOneof(const OneofDescriptor& oneof) const; diff --git a/src/google/protobuf/compiler/python/pyi_generator.cc b/src/google/protobuf/compiler/python/pyi_generator.cc index 13b67d2bc0..7f7bfeda08 100644 --- a/src/google/protobuf/compiler/python/pyi_generator.cc +++ b/src/google/protobuf/compiler/python/pyi_generator.cc @@ -17,6 +17,8 @@ #include "absl/strings/ascii.h" #include "absl/strings/match.h" #include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/python/helpers.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" @@ -168,6 +170,9 @@ void PyiGenerator::PrintImports() const { bool has_importlib = false; for (int i = 0; i < file_->dependency_count(); ++i) { const FileDescriptor* dep = file_->dependency(i); + if (strip_nonfunctional_codegen_ && IsKnownFeatureProto(dep->name())) { + continue; + } PrintImportForDescriptor(*dep, &seen_aliases, &has_importlib); for (int j = 0; j < dep->public_dependency_count(); ++j) { PrintImportForDescriptor(*dep->public_dependency(j), &seen_aliases, @@ -569,11 +574,14 @@ bool PyiGenerator::Generate(const FileDescriptor* file, std::string filename; bool annotate_code = false; + strip_nonfunctional_codegen_ = false; for (const std::pair& option : options) { if (option.first == "annotate_code") { annotate_code = true; } else if (absl::EndsWith(option.first, ".pyi")) { filename = option.first; + } else if (option.first == "experimental_strip_nonfunctional_codegen") { + strip_nonfunctional_codegen_ = true; } else { *error = absl::StrCat("Unknown generator option: ", option.first); return false; diff --git a/src/google/protobuf/compiler/python/pyi_generator.h b/src/google/protobuf/compiler/python/pyi_generator.h index 84c802bee8..495b296900 100644 --- a/src/google/protobuf/compiler/python/pyi_generator.h +++ b/src/google/protobuf/compiler/python/pyi_generator.h @@ -13,6 +13,7 @@ #define GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__ #include +#include #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" @@ -53,6 +54,12 @@ class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenera GeneratorContext* generator_context, std::string* error) const override; + Edition GetMinimumEdition() const override { return Edition::EDITION_PROTO2; } + Edition GetMaximumEdition() const override { return Edition::EDITION_2023; } + std::vector GetFeatureExtensions() const override { + return {}; + } + private: void PrintImportForDescriptor(const FileDescriptor& desc, absl::flat_hash_set* seen_aliases, @@ -83,6 +90,7 @@ class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenera mutable absl::Mutex mutex_; mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_. mutable io::Printer* printer_; // Set in Generate(). Under mutex_. + mutable bool strip_nonfunctional_codegen_ = false; // Set in Generate(). // import_map will be a mapping from filename to module alias, e.g. // "google3/foo/bar.py" -> "_bar" mutable absl::flat_hash_map import_map_; diff --git a/src/google/protobuf/compiler/ruby/BUILD.bazel b/src/google/protobuf/compiler/ruby/BUILD.bazel index d01764c2ff..62afc3c35a 100644 --- a/src/google/protobuf/compiler/ruby/BUILD.bazel +++ b/src/google/protobuf/compiler/ruby/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( srcs = ["ruby_generator.cc"], hdrs = ["ruby_generator.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/ruby", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/rust/BUILD.bazel b/src/google/protobuf/compiler/rust/BUILD.bazel index f404beae97..9939c2ca21 100644 --- a/src/google/protobuf/compiler/rust/BUILD.bazel +++ b/src/google/protobuf/compiler/rust/BUILD.bazel @@ -10,7 +10,7 @@ cc_library( srcs = ["generator.cc"], hdrs = ["generator.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", @@ -34,7 +34,7 @@ cc_library( srcs = ["message.cc"], hdrs = ["message.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ ":accessors", ":context", @@ -51,6 +51,7 @@ cc_library( name = "accessors", srcs = [ "accessors/accessors.cc", + "accessors/repeated_scalar.cc", "accessors/singular_message.cc", "accessors/singular_scalar.cc", "accessors/singular_string.cc", @@ -61,7 +62,7 @@ cc_library( "accessors/accessors.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ ":context", ":naming", @@ -77,7 +78,7 @@ cc_library( srcs = ["context.cc"], hdrs = ["context.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ "//src/google/protobuf/compiler:code_generator", "//src/google/protobuf/io:printer", @@ -95,7 +96,7 @@ cc_library( srcs = ["naming.cc"], hdrs = ["naming.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ ":context", "//src/google/protobuf:protobuf_nowkt", @@ -109,7 +110,7 @@ cc_library( srcs = ["oneof.cc"], hdrs = ["oneof.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ ":context", ":naming", @@ -123,7 +124,7 @@ cc_library( name = "relative_path", srcs = ["relative_path.cc"], hdrs = ["relative_path.h"], - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/log:absl_check", diff --git a/src/google/protobuf/compiler/rust/accessors/accessor_generator.h b/src/google/protobuf/compiler/rust/accessors/accessor_generator.h index e3a453493c..8b26d19dc8 100644 --- a/src/google/protobuf/compiler/rust/accessors/accessor_generator.h +++ b/src/google/protobuf/compiler/rust/accessors/accessor_generator.h @@ -9,6 +9,8 @@ #define GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_ACCESSOR_GENERATOR_H__ #include +#include +#include #include "absl/log/absl_check.h" #include "google/protobuf/compiler/rust/context.h" @@ -86,10 +88,22 @@ class SingularMessage final : public AccessorGenerator { void InThunkCc(Context field) const override; }; +class RepeatedScalar final : public AccessorGenerator { + public: + ~RepeatedScalar() override = default; + void InMsgImpl(Context field) const override; + void InExternC(Context field) const override; + void InThunkCc(Context field) const override; +}; + class UnsupportedField final : public AccessorGenerator { public: + explicit UnsupportedField(std::string reason) : reason_(std::move(reason)) {} ~UnsupportedField() override = default; void InMsgImpl(Context field) const override; + + private: + std::string reason_; }; } // namespace rust diff --git a/src/google/protobuf/compiler/rust/accessors/accessors.cc b/src/google/protobuf/compiler/rust/accessors/accessors.cc index 82b38cc642..e963e9e075 100644 --- a/src/google/protobuf/compiler/rust/accessors/accessors.cc +++ b/src/google/protobuf/compiler/rust/accessors/accessors.cc @@ -9,6 +9,7 @@ #include +#include "absl/log/absl_log.h" #include "google/protobuf/compiler/rust/accessors/accessor_generator.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/descriptor.h" @@ -23,14 +24,11 @@ namespace { std::unique_ptr AccessorGeneratorFor( const FieldDescriptor& desc) { - // We do not support [ctype=FOO] (used to set the field type in C++ to - // cord or string_piece) in V0 API. + // TODO: We do not support [ctype=FOO] (used to set the field + // type in C++ to cord or string_piece) in V0.6 API. if (desc.options().has_ctype()) { - return std::make_unique(); - } - - if (desc.is_repeated()) { - return std::make_unique(); + return std::make_unique( + "fields with ctype not supported"); } switch (desc.type()) { @@ -47,16 +45,30 @@ std::unique_ptr AccessorGeneratorFor( case FieldDescriptor::TYPE_FLOAT: case FieldDescriptor::TYPE_DOUBLE: case FieldDescriptor::TYPE_BOOL: + if (desc.is_repeated()) { + return std::make_unique(); + } return std::make_unique(); case FieldDescriptor::TYPE_BYTES: case FieldDescriptor::TYPE_STRING: + if (desc.is_repeated()) { + return std::make_unique("repeated str not supported"); + } return std::make_unique(); case FieldDescriptor::TYPE_MESSAGE: + if (desc.is_repeated()) { + return std::make_unique("repeated msg not supported"); + } return std::make_unique(); - default: - return std::make_unique(); + case FieldDescriptor::TYPE_ENUM: + return std::make_unique("enum not supported"); + + case FieldDescriptor::TYPE_GROUP: + return std::make_unique("group not supported"); } + + ABSL_LOG(FATAL) << "Unexpected field type: " << desc.type(); } } // namespace diff --git a/src/google/protobuf/compiler/rust/accessors/repeated_scalar.cc b/src/google/protobuf/compiler/rust/accessors/repeated_scalar.cc new file mode 100644 index 0000000000..8f0a7625b3 --- /dev/null +++ b/src/google/protobuf/compiler/rust/accessors/repeated_scalar.cc @@ -0,0 +1,156 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2023 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" +#include "google/protobuf/compiler/rust/context.h" +#include "google/protobuf/compiler/rust/naming.h" +#include "google/protobuf/descriptor.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace rust { + +void RepeatedScalar::InMsgImpl(Context field) const { + field.Emit({{"field", field.desc().name()}, + {"Scalar", PrimitiveRsTypeName(field.desc())}, + {"getter_thunk", Thunk(field, "get")}, + {"getter_mut_thunk", Thunk(field, "get_mut")}, + {"getter", + [&] { + if (field.is_upb()) { + field.Emit({}, R"rs( + pub fn r#$field$(&self) -> $pb$::RepeatedView<'_, $Scalar$> { + let inner = unsafe { + $getter_thunk$( + self.inner.msg, + /* optional size pointer */ std::ptr::null(), + ) } + .map_or_else(|| unsafe {$pbr$::empty_array()}, |raw| { + $pbr$::RepeatedFieldInner{ raw, arena: &self.inner.arena } + }); + $pb$::RepeatedView::from_inner($pbi$::Private, inner) + } + )rs"); + } else { + field.Emit({}, R"rs( + pub fn r#$field$(&self) -> $pb$::RepeatedView<'_, $Scalar$> { + $pb$::RepeatedView::from_inner( + $pbi$::Private, + $pbr$::RepeatedFieldInner{ + raw: unsafe { $getter_thunk$(self.inner.msg) }, + _phantom: std::marker::PhantomData, + }, + ) + } + )rs"); + } + }}, + {"clearer_thunk", Thunk(field, "clear")}, + {"field_mutator_getter", + [&] { + if (field.is_upb()) { + field.Emit({}, R"rs( + pub fn r#$field$_mut(&mut self) -> $pb$::RepeatedMut<'_, $Scalar$> { + $pb$::RepeatedMut::from_inner( + $pbi$::Private, + $pbr$::RepeatedFieldInner{ + raw: unsafe { $getter_mut_thunk$( + self.inner.msg, + /* optional size pointer */ std::ptr::null(), + self.inner.arena.raw(), + ) }, + arena: &self.inner.arena, + }, + ) + } + )rs"); + } else { + field.Emit({}, R"rs( + pub fn r#$field$_mut(&mut self) -> $pb$::RepeatedMut<'_, $Scalar$> { + $pb$::RepeatedMut::from_inner( + $pbi$::Private, + $pbr$::RepeatedFieldInner{ + raw: unsafe { $getter_mut_thunk$(self.inner.msg)}, + _phantom: std::marker::PhantomData, + }, + ) + } + )rs"); + } + }}}, + R"rs( + $getter$ + $field_mutator_getter$ + )rs"); +} + +void RepeatedScalar::InExternC(Context field) const { + field.Emit({{"Scalar", PrimitiveRsTypeName(field.desc())}, + {"getter_thunk", Thunk(field, "get")}, + {"getter_mut_thunk", Thunk(field, "get_mut")}, + {"getter", + [&] { + if (field.is_upb()) { + field.Emit(R"rs( + fn $getter_mut_thunk$( + raw_msg: $pbi$::RawMessage, + size: *const usize, + arena: $pbi$::RawArena, + ) -> $pbi$::RawRepeatedField; + // Returns `None` when returned array pointer is NULL. + fn $getter_thunk$( + raw_msg: $pbi$::RawMessage, + size: *const usize, + ) -> Option<$pbi$::RawRepeatedField>; + )rs"); + } else { + field.Emit(R"rs( + fn $getter_mut_thunk$(raw_msg: $pbi$::RawMessage) -> $pbi$::RawRepeatedField; + fn $getter_thunk$(raw_msg: $pbi$::RawMessage) -> $pbi$::RawRepeatedField; + )rs"); + } + }}, + {"clearer_thunk", Thunk(field, "clear")}}, + R"rs( + fn $clearer_thunk$(raw_msg: $pbi$::RawMessage); + $getter$ + )rs"); +} + +void RepeatedScalar::InThunkCc(Context field) const { + field.Emit({{"field", cpp::FieldName(&field.desc())}, + {"Scalar", cpp::PrimitiveTypeName(field.desc().cpp_type())}, + {"QualifiedMsg", + cpp::QualifiedClassName(field.desc().containing_type())}, + {"clearer_thunk", Thunk(field, "clear")}, + {"getter_thunk", Thunk(field, "get")}, + {"getter_mut_thunk", Thunk(field, "get_mut")}, + {"impls", + [&] { + field.Emit( + R"cc( + void $clearer_thunk$($QualifiedMsg$* msg) { + msg->clear_$field$(); + } + google::protobuf::RepeatedField<$Scalar$>* $getter_mut_thunk$($QualifiedMsg$* msg) { + return msg->mutable_$field$(); + } + const google::protobuf::RepeatedField<$Scalar$>& $getter_thunk$($QualifiedMsg$& msg) { + return msg.$field$(); + } + )cc"); + }}}, + "$impls$"); +} + +} // namespace rust +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/rust/accessors/singular_message.cc b/src/google/protobuf/compiler/rust/accessors/singular_message.cc index 7c3d3adbe3..2978631faf 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_message.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_message.cc @@ -51,7 +51,7 @@ void SingularMessage::InMsgImpl(Context field) const { // a null ptr received from upb manifests as Option::None match submsg { // TODO:(b/304357029) - None => $prefix$View::new($pbi$::Private, $pbr$::ScratchSpace::zeroed_block()), + None => $prefix$View::new($pbi$::Private, $pbr$::ScratchSpace::zeroed_block($pbi$::Private)), Some(field) => $prefix$View::new($pbi$::Private, field), } } diff --git a/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc b/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc index 3f8594bb16..b7b7a55643 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc @@ -5,12 +5,20 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#include +#include +#include + +#include "absl/log/absl_log.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_generator.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/naming.h" #include "google/protobuf/descriptor.h" +#include "google/protobuf/io/strtod.h" namespace google { namespace protobuf { @@ -23,6 +31,72 @@ void SingularScalar::InMsgImpl(Context field) const { {"field", field.desc().name()}, {"Scalar", PrimitiveRsTypeName(field.desc())}, {"hazzer_thunk", Thunk(field, "has")}, + {"default_value", + [&] { + switch (field.desc().type()) { + case FieldDescriptor::TYPE_DOUBLE: + if (std::isfinite(field.desc().default_value_double())) { + return absl::StrCat( + io::SimpleDtoa(field.desc().default_value_double()), + "f64"); + } else if (std::isnan(field.desc().default_value_double())) { + return std::string("f64::NAN"); + } else if (field.desc().default_value_double() == + std::numeric_limits::infinity()) { + return std::string("f64::INFINITY"); + } else if (field.desc().default_value_double() == + -std::numeric_limits::infinity()) { + return std::string("f64::NEG_INFINITY"); + } else { + ABSL_LOG(FATAL) << "unreachable"; + } + case FieldDescriptor::TYPE_FLOAT: + if (std::isfinite(field.desc().default_value_float())) { + return absl::StrCat( + io::SimpleFtoa(field.desc().default_value_float()), + "f32"); + } else if (std::isnan(field.desc().default_value_float())) { + return std::string("f32::NAN"); + } else if (field.desc().default_value_float() == + std::numeric_limits::infinity()) { + return std::string("f32::INFINITY"); + } else if (field.desc().default_value_float() == + -std::numeric_limits::infinity()) { + return std::string("f32::NEG_INFINITY"); + } else { + ABSL_LOG(FATAL) << "unreachable"; + } + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_SINT32: + return absl::StrFormat("%d", + field.desc().default_value_int32()); + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SFIXED64: + case FieldDescriptor::TYPE_SINT64: + return absl::StrFormat("%d", + field.desc().default_value_int64()); + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_UINT64: + return absl::StrFormat("%u", + field.desc().default_value_uint64()); + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_UINT32: + return absl::StrFormat("%u", + field.desc().default_value_uint32()); + case FieldDescriptor::TYPE_BOOL: + return absl::StrFormat("%v", + field.desc().default_value_bool()); + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_BYTES: + case FieldDescriptor::TYPE_ENUM: + ABSL_LOG(FATAL) << "Non-singular scalar field type passed: " + << field.desc().type_name(); + } + ABSL_LOG(FATAL) << "unreachable"; + }()}, {"getter", [&] { field.Emit({}, R"rs( @@ -38,7 +112,7 @@ void SingularScalar::InMsgImpl(Context field) const { field.Emit({}, R"rs( pub fn r#$field$_opt(&self) -> $pb$::Optional<$Scalar$> { if !unsafe { $hazzer_thunk$(self.inner.msg) } { - return $pb$::Optional::Unset(<$Scalar$>::default()); + return $pb$::Optional::Unset($default_value$); } let value = unsafe { $getter_thunk$(self.inner.msg) }; $pb$::Optional::Set(value) @@ -64,11 +138,31 @@ void SingularScalar::InMsgImpl(Context field) const { {"field_mutator_getter", [&] { if (field.desc().has_presence()) { - // TODO: implement mutator for fields with presence. - return; + field.Emit({}, R"rs( + pub fn r#$field$_mut(&mut self) -> $pb$::FieldEntry<'_, $Scalar$> { + static VTABLE: $pbi$::PrimitiveOptionalMutVTable<$Scalar$> = + $pbi$::PrimitiveOptionalMutVTable::new( + $pbi$::Private, + $getter_thunk$, + $setter_thunk$, + $clearer_thunk$, + $default_value$, + ); + + unsafe { + let has = $hazzer_thunk$(self.inner.msg); + $pbi$::new_vtable_field_entry::<$Scalar$>( + $pbi$::Private, + $pbr$::MutatorMessageRef::new($pbi$::Private, &mut self.inner), + &VTABLE, + has, + ) + } + } + )rs"); } else { field.Emit({}, R"rs( - pub fn r#$field$_mut(&mut self) -> $pb$::PrimitiveMut<'_, $Scalar$> { + pub fn r#$field$_mut(&mut self) -> $pb$::Mut<'_, $Scalar$> { static VTABLE: $pbi$::PrimitiveVTable<$Scalar$> = $pbi$::PrimitiveVTable::new( $pbi$::Private, @@ -76,7 +170,7 @@ void SingularScalar::InMsgImpl(Context field) const { $setter_thunk$, ); - $pb$::PrimitiveMut::from_inner( + $pb$::PrimitiveMut::from_singular( $pbi$::Private, unsafe { $pbi$::RawVTableMutator::new( diff --git a/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc b/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc index ad0a98901c..e6bce02171 100644 --- a/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc +++ b/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc @@ -16,8 +16,8 @@ namespace compiler { namespace rust { void UnsupportedField::InMsgImpl(Context field) const { - field.Emit(R"rs( - // Unsupported! :( + field.Emit({{"reason", reason_}}, R"rs( + // Unsupported! :( Reason: $reason$ )rs"); field.printer().PrintRaw("\n"); } diff --git a/src/google/protobuf/compiler/rust/naming.cc b/src/google/protobuf/compiler/rust/naming.cc index eb0b30b905..bb1c35a3e2 100644 --- a/src/google/protobuf/compiler/rust/naming.cc +++ b/src/google/protobuf/compiler/rust/naming.cc @@ -64,22 +64,28 @@ std::string GetHeaderFile(Context file) { namespace { template -std::string Thunk(Context field, absl::string_view op) { +std::string FieldPrefix(Context field) { // NOTE: When field.is_upb(), this functions outputs must match the symbols // that the upbc plugin generates exactly. Failure to do so correctly results // in a link-time failure. absl::string_view prefix = field.is_cpp() ? "__rust_proto_thunk__" : ""; - std::string thunk = + std::string thunk_prefix = absl::StrCat(prefix, GetUnderscoreDelimitedFullName( field.WithDesc(field.desc().containing_type()))); + return thunk_prefix; +} + +template +std::string Thunk(Context field, absl::string_view op) { + std::string thunk = FieldPrefix(field); absl::string_view format; if (field.is_upb() && op == "get") { // upb getter is simply the field name (no "get" in the name). format = "_$1"; - } else if (field.is_upb() && op == "case") { - // upb oneof case function is x_case compared to has/set/clear which are in - // the other order e.g. clear_x. + } else if (field.is_upb() && (op == "case")) { + // some upb functions are in the order x_op compared to has/set/clear which + // are in the other order e.g. op_x. format = "_$1_$0"; } else { format = "_$0_$1"; @@ -89,9 +95,32 @@ std::string Thunk(Context field, absl::string_view op) { return thunk; } +std::string ThunkRepeated(Context field, + absl::string_view op) { + if (!field.is_upb()) { + return Thunk(field, op); + } + + std::string thunk = absl::StrCat("_", FieldPrefix(field)); + absl::string_view format; + if (op == "get") { + format = "_$1_upb_array"; + } else if (op == "get_mut") { + format = "_$1_mutable_upb_array"; + } else { + return Thunk(field, op); + } + + absl::SubstituteAndAppend(&thunk, format, op, field.desc().name()); + return thunk; +} + } // namespace std::string Thunk(Context field, absl::string_view op) { + if (field.desc().is_repeated()) { + return ThunkRepeated(field, op); + } return Thunk(field, op); } diff --git a/src/google/protobuf/compiler/rust/oneof.cc b/src/google/protobuf/compiler/rust/oneof.cc index 2cdeeac203..41f5bb9a1c 100644 --- a/src/google/protobuf/compiler/rust/oneof.cc +++ b/src/google/protobuf/compiler/rust/oneof.cc @@ -92,12 +92,15 @@ std::string oneofCaseEnumName(const OneofDescriptor& desc) { // TODO: Promote up to naming.h once all types can be spelled. std::string RsTypeName(const FieldDescriptor& desc) { + // TODO: Fields with a ctype set not supported in v0.6 api. + if (desc.options().has_ctype()) { + return ""; + } + switch (desc.type()) { case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_ENUM: case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: return ""; default: return PrimitiveRsTypeName(desc); diff --git a/src/google/protobuf/cpp_features.pb.cc b/src/google/protobuf/cpp_features.pb.cc index ec3d53d733..b7eee1a5fa 100644 --- a/src/google/protobuf/cpp_features.pb.cc +++ b/src/google/protobuf/cpp_features.pb.cc @@ -46,29 +46,31 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2fcpp_5ffeatures_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fcpp_5ffeatures_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fcpp_5ffeatures_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _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(::pb::CppFeatures, _impl_.legacy_closed_enum_), - 0, +const ::uint32_t + TableStruct_google_2fprotobuf_2fcpp_5ffeatures_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _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(::pb::CppFeatures, _impl_.legacy_closed_enum_), + 0, }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, 9, -1, sizeof(::pb::CppFeatures)}, }; static const ::_pb::Message* const file_default_instances[] = { &::pb::_CppFeatures_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fcpp_5ffeatures_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fcpp_5ffeatures_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\"google/protobuf/cpp_features.proto\022\002pb" "\032 google/protobuf/descriptor.proto\"M\n\013Cp" "pFeatures\022>\n\022legacy_closed_enum\030\001 \001(\010B\"\210" @@ -155,6 +157,16 @@ inline void CppFeatures::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +CppFeatures::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + CppFeatures::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void CppFeatures::Clear() { // @@protoc_insertion_point(message_clear_start:pb.CppFeatures) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -245,13 +257,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> CppFeatures::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData CppFeatures::_class_data_ = { - CppFeatures::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* CppFeatures::GetClassData() const { - return &_class_data_; -} void CppFeatures::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/cpp_features.pb.h b/src/google/protobuf/cpp_features.pb.h index 8407117a38..01d610cdf1 100644 --- a/src/google/protobuf/cpp_features.pb.h +++ b/src/google/protobuf/cpp_features.pb.h @@ -170,7 +170,7 @@ class PROTOBUF_EXPORT CppFeatures final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -193,11 +193,9 @@ class PROTOBUF_EXPORT CppFeatures final : protected: explicit CppFeatures(::google::protobuf::Arena* arena); CppFeatures(::google::protobuf::Arena* arena, const CppFeatures& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 5be4ddf37a..0f1cd6bc86 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -1266,7 +1266,7 @@ class FileDescriptorTables { FieldsByNumberSet fields_by_number_; // Not including extensions. EnumValuesByNumberSet enum_values_by_number_; mutable EnumValuesByNumberSet unknown_enum_values_by_number_ - PROTOBUF_GUARDED_BY(unknown_enum_values_mu_); + ABSL_GUARDED_BY(unknown_enum_values_mu_); // Populated on first request to save space, hence constness games. mutable absl::once_flag locations_by_path_once_; @@ -7877,10 +7877,22 @@ static bool IsStringMapType(const FieldDescriptor& field) { void DescriptorBuilder::ValidateFileFeatures(const FileDescriptor* file, const FileDescriptorProto& proto) { + // Rely on our legacy validation for proto2/proto3 files. + if (FileDescriptorLegacy(file).syntax() != + FileDescriptorLegacy::SYNTAX_EDITIONS) { + return; + } + if (file->features().field_presence() == FeatureSet::LEGACY_REQUIRED) { AddError(file->name(), proto, DescriptorPool::ErrorCollector::EDITIONS, "Required presence can't be specified by default."); } + if (file->options().java_string_check_utf8()) { + AddError( + file->name(), proto, DescriptorPool::ErrorCollector::EDITIONS, + "File option java_string_check_utf8 is not allowed under editions. Use " + "the (pb.java).utf8_validation feature to control this behavior."); + } } void DescriptorBuilder::ValidateFieldFeatures( diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index ff178c31c9..115a1f86a5 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -49,6 +49,7 @@ #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "absl/types/optional.h" +#include "google/protobuf/descriptor_lite.h" #include "google/protobuf/extension_set.h" #include "google/protobuf/port.h" @@ -731,7 +732,8 @@ PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(Descriptor, 152); // - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber() or // DescriptorPool::FindExtensionByPrintableName(). // Use DescriptorPool to construct your own descriptors. -class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase { +class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, + public internal::FieldDescriptorLite { public: typedef FieldDescriptorProto Proto; @@ -742,64 +744,67 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase { // 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 { - TYPE_DOUBLE = 1, // double, exactly eight bytes on the wire. - TYPE_FLOAT = 2, // float, exactly four bytes on the wire. - TYPE_INT64 = 3, // int64, varint on the wire. Negative numbers - // take 10 bytes. Use TYPE_SINT64 if negative - // values are likely. - TYPE_UINT64 = 4, // uint64, varint on the wire. - TYPE_INT32 = 5, // int32, varint on the wire. Negative numbers - // take 10 bytes. Use TYPE_SINT32 if negative - // values are likely. - TYPE_FIXED64 = 6, // uint64, exactly eight bytes on the wire. - TYPE_FIXED32 = 7, // uint32, exactly four bytes on the wire. - TYPE_BOOL = 8, // bool, varint on the wire. - TYPE_STRING = 9, // UTF-8 text. - TYPE_GROUP = 10, // Tag-delimited message. Deprecated. - TYPE_MESSAGE = 11, // Length-delimited message. - - TYPE_BYTES = 12, // Arbitrary byte array. - TYPE_UINT32 = 13, // uint32, varint on the wire - TYPE_ENUM = 14, // Enum, varint on the wire - TYPE_SFIXED32 = 15, // int32, exactly four bytes on the wire - TYPE_SFIXED64 = 16, // int64, exactly eight bytes on the wire - TYPE_SINT32 = 17, // int32, ZigZag-encoded varint on the wire - TYPE_SINT64 = 18, // int64, ZigZag-encoded varint on the wire - - MAX_TYPE = 18, // Constant useful for defining lookup tables - // indexed by Type. - }; + // Inherited from FieldDescriptorLite: + // enum Type { + // TYPE_DOUBLE = 1, // double, exactly eight bytes on the wire. + // TYPE_FLOAT = 2, // float, exactly four bytes on the wire. + // TYPE_INT64 = 3, // int64, varint on the wire. Negative numbers + // // take 10 bytes. Use TYPE_SINT64 if negative + // // values are likely. + // TYPE_UINT64 = 4, // uint64, varint on the wire. + // TYPE_INT32 = 5, // int32, varint on the wire. Negative numbers + // // take 10 bytes. Use TYPE_SINT32 if negative + // // values are likely. + // TYPE_FIXED64 = 6, // uint64, exactly eight bytes on the wire. + // TYPE_FIXED32 = 7, // uint32, exactly four bytes on the wire. + // TYPE_BOOL = 8, // bool, varint on the wire. + // TYPE_STRING = 9, // UTF-8 text. + // TYPE_GROUP = 10, // Tag-delimited message. Deprecated. + // TYPE_MESSAGE = 11, // Length-delimited message. + + // TYPE_BYTES = 12, // Arbitrary byte array. + // TYPE_UINT32 = 13, // uint32, varint on the wire + // TYPE_ENUM = 14, // Enum, varint on the wire + // TYPE_SFIXED32 = 15, // int32, exactly four bytes on the wire + // TYPE_SFIXED64 = 16, // int64, exactly eight bytes on the wire + // TYPE_SINT32 = 17, // int32, ZigZag-encoded varint on the wire + // TYPE_SINT64 = 18, // int64, ZigZag-encoded varint on the wire + + // MAX_TYPE = 18, // Constant useful for defining lookup tables + // // indexed by Type. + // }; // Specifies the C++ data type used to represent the field. There is a // fixed mapping from Type to CppType where each Type maps to exactly one // CppType. 0 is reserved for errors. - enum CppType { - CPPTYPE_INT32 = 1, // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32 - CPPTYPE_INT64 = 2, // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64 - CPPTYPE_UINT32 = 3, // TYPE_UINT32, TYPE_FIXED32 - CPPTYPE_UINT64 = 4, // TYPE_UINT64, TYPE_FIXED64 - CPPTYPE_DOUBLE = 5, // TYPE_DOUBLE - CPPTYPE_FLOAT = 6, // TYPE_FLOAT - CPPTYPE_BOOL = 7, // TYPE_BOOL - CPPTYPE_ENUM = 8, // TYPE_ENUM - CPPTYPE_STRING = 9, // TYPE_STRING, TYPE_BYTES - CPPTYPE_MESSAGE = 10, // TYPE_MESSAGE, TYPE_GROUP - - MAX_CPPTYPE = 10, // Constant useful for defining lookup tables - // indexed by CppType. - }; + // Inherited from FieldDescriptorLite: + // enum CppType { + // CPPTYPE_INT32 = 1, // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32 + // CPPTYPE_INT64 = 2, // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64 + // CPPTYPE_UINT32 = 3, // TYPE_UINT32, TYPE_FIXED32 + // CPPTYPE_UINT64 = 4, // TYPE_UINT64, TYPE_FIXED64 + // CPPTYPE_DOUBLE = 5, // TYPE_DOUBLE + // CPPTYPE_FLOAT = 6, // TYPE_FLOAT + // CPPTYPE_BOOL = 7, // TYPE_BOOL + // CPPTYPE_ENUM = 8, // TYPE_ENUM + // CPPTYPE_STRING = 9, // TYPE_STRING, TYPE_BYTES + // CPPTYPE_MESSAGE = 10, // TYPE_MESSAGE, TYPE_GROUP + + // MAX_CPPTYPE = 10, // Constant useful for defining lookup tables + // // indexed by CppType. + // }; // Identifies whether the field is optional, required, or repeated. 0 is // reserved for errors. - enum Label { - LABEL_OPTIONAL = 1, // optional - LABEL_REQUIRED = 2, // required - LABEL_REPEATED = 3, // repeated - - MAX_LABEL = 3, // Constant useful for defining lookup tables - // indexed by Label. - }; + // Inherited from FieldDescriptorLite: + // enum Label { + // LABEL_OPTIONAL = 1, // optional + // LABEL_REQUIRED = 2, // required + // LABEL_REPEATED = 3, // repeated + + // MAX_LABEL = 3, // Constant useful for defining lookup tables + // // indexed by Label. + // }; // Valid field numbers are positive integers up to kMaxNumber. static const int kMaxNumber = (1 << 29) - 1; diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 8e880a77c7..ae02aa9a2d 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1003,593 +1003,594 @@ static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fdescriptor_2eprot static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[17]; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorSet, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorSet, _impl_.file_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.package_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.dependency_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.public_dependency_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.weak_dependency_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.message_type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.enum_type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.service_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.extension_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.source_code_info_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.syntax_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.edition_), - 0, - 1, - ~0u, - ~0u, - ~0u, - ~0u, - ~0u, - ~0u, - ~0u, - 3, - 4, - 2, - 5, - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ExtensionRange, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::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(::google::protobuf::DescriptorProto_ExtensionRange, _impl_.start_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ExtensionRange, _impl_.end_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ExtensionRange, _impl_.options_), - 1, - 2, - 0, - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ReservedRange, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ReservedRange, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ReservedRange, _impl_.start_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ReservedRange, _impl_.end_), - 0, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.field_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.extension_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.nested_type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.enum_type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.extension_range_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.oneof_decl_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.reserved_range_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.reserved_name_), - 0, - ~0u, - ~0u, - ~0u, - ~0u, - ~0u, - ~0u, - 1, - ~0u, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _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(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.number_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.full_name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.reserved_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.repeated_), - 2, - 0, - 1, - 3, - 4, - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.uninterpreted_option_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.declaration_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.verification_), - ~0u, - ~0u, - 0, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.number_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.label_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.type_name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.extendee_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.default_value_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.oneof_index_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.json_name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.proto3_optional_), - 0, - 6, - 9, - 10, - 2, - 1, - 3, - 7, - 4, - 5, - 8, - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofDescriptorProto, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofDescriptorProto, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofDescriptorProto, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofDescriptorProto, _impl_.options_), - 0, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto_EnumReservedRange, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto_EnumReservedRange, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto_EnumReservedRange, _impl_.start_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto_EnumReservedRange, _impl_.end_), - 0, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.value_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.reserved_range_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.reserved_name_), - 0, - ~0u, - 1, - ~0u, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _impl_.number_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _impl_.options_), - 0, - 2, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _impl_.method_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _impl_.options_), - 0, - ~0u, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.input_type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.output_type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.client_streaming_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.server_streaming_), - 0, - 1, - 2, - 3, - 4, - 5, - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_package_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_outer_classname_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_multiple_files_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_generate_equals_and_hash_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_string_check_utf8_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.optimize_for_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.go_package_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.cc_generic_services_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_generic_services_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.py_generic_services_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.php_generic_services_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.deprecated_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.cc_enable_arenas_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.objc_class_prefix_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.csharp_namespace_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.swift_prefix_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.php_class_prefix_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.php_namespace_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.php_metadata_namespace_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.ruby_package_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.uninterpreted_option_), - 0, - 1, - 11, - 12, - 13, - 19, - 2, - 14, - 15, - 16, - 17, - 18, - 20, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.message_set_wire_format_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.no_standard_descriptor_accessor_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.deprecated_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.map_entry_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.deprecated_legacy_json_field_conflicts_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.uninterpreted_option_), - 1, - 2, - 3, - 4, - 5, - 0, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions_EditionDefault, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions_EditionDefault, _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(::google::protobuf::FieldOptions_EditionDefault, _impl_.edition_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions_EditionDefault, _impl_.value_), - 1, - 0, - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.ctype_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.packed_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.jstype_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.lazy_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.unverified_lazy_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.deprecated_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.weak_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.debug_redact_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.retention_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.targets_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.edition_defaults_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.uninterpreted_option_), - 1, - 3, - 2, - 4, - 5, - 6, - 7, - 8, - 9, - ~0u, - ~0u, - 0, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _impl_.uninterpreted_option_), - 0, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.allow_alias_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.deprecated_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.deprecated_legacy_json_field_conflicts_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.uninterpreted_option_), - 1, - 2, - 3, - 0, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.deprecated_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.debug_redact_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.uninterpreted_option_), - 1, - 0, - 2, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_.deprecated_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_.uninterpreted_option_), - 0, - 1, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.deprecated_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.idempotency_level_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.features_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.uninterpreted_option_), - 1, - 2, - 0, - ~0u, - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption_NamePart, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption_NamePart, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption_NamePart, _impl_.name_part_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption_NamePart, _impl_.is_extension_), - 0, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.identifier_value_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.positive_int_value_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.negative_int_value_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.double_value_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.string_value_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.aggregate_value_), - ~0u, - 0, - 3, - 4, - 5, - 1, - 2, - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _internal_metadata_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_._extensions_), - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.field_presence_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.enum_type_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.repeated_field_encoding_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.utf8_validation_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.message_encoding_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.json_format_), - 0, - 1, - 2, - 3, - 4, - 5, - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault, _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(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault, _impl_.edition_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault, _impl_.features_), - 1, - 0, - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults, _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(::google::protobuf::FeatureSetDefaults, _impl_.defaults_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults, _impl_.minimum_edition_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults, _impl_.maximum_edition_), - ~0u, - 0, - 1, - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.path_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.span_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.leading_comments_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.trailing_comments_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.leading_detached_comments_), - ~0u, - ~0u, - 0, - 1, - ~0u, - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo, _impl_.location_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.path_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.source_file_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.begin_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.end_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.semantic_), - ~0u, - 0, - 1, - 2, - 3, - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::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(::google::protobuf::GeneratedCodeInfo, _impl_.annotation_), +const ::uint32_t + TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorSet, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorSet, _impl_.file_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.package_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.dependency_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.public_dependency_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.weak_dependency_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.message_type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.enum_type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.service_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.extension_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.source_code_info_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.syntax_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorProto, _impl_.edition_), + 0, + 1, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + 3, + 4, + 2, + 5, + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ExtensionRange, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::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(::google::protobuf::DescriptorProto_ExtensionRange, _impl_.start_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ExtensionRange, _impl_.end_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ExtensionRange, _impl_.options_), + 1, + 2, + 0, + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ReservedRange, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ReservedRange, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ReservedRange, _impl_.start_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto_ReservedRange, _impl_.end_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.field_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.extension_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.nested_type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.enum_type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.extension_range_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.oneof_decl_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.reserved_range_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::DescriptorProto, _impl_.reserved_name_), + 0, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + 1, + ~0u, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _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(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.full_name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.reserved_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions_Declaration, _impl_.repeated_), + 2, + 0, + 1, + 3, + 4, + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.declaration_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ExtensionRangeOptions, _impl_.verification_), + ~0u, + ~0u, + 0, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.label_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.type_name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.extendee_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.default_value_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.oneof_index_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.json_name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldDescriptorProto, _impl_.proto3_optional_), + 0, + 6, + 9, + 10, + 2, + 1, + 3, + 7, + 4, + 5, + 8, + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofDescriptorProto, _impl_.options_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto_EnumReservedRange, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto_EnumReservedRange, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto_EnumReservedRange, _impl_.start_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto_EnumReservedRange, _impl_.end_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.value_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.reserved_range_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumDescriptorProto, _impl_.reserved_name_), + 0, + ~0u, + 1, + ~0u, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueDescriptorProto, _impl_.options_), + 0, + 2, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _impl_.method_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceDescriptorProto, _impl_.options_), + 0, + ~0u, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.input_type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.output_type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.client_streaming_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodDescriptorProto, _impl_.server_streaming_), + 0, + 1, + 2, + 3, + 4, + 5, + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_package_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_outer_classname_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_multiple_files_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_generate_equals_and_hash_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_string_check_utf8_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.optimize_for_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.go_package_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.cc_generic_services_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.java_generic_services_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.py_generic_services_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.php_generic_services_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.cc_enable_arenas_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.objc_class_prefix_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.csharp_namespace_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.swift_prefix_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.php_class_prefix_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.php_namespace_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.php_metadata_namespace_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.ruby_package_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileOptions, _impl_.uninterpreted_option_), + 0, + 1, + 11, + 12, + 13, + 19, + 2, + 14, + 15, + 16, + 17, + 18, + 20, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.message_set_wire_format_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.no_standard_descriptor_accessor_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.map_entry_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.deprecated_legacy_json_field_conflicts_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MessageOptions, _impl_.uninterpreted_option_), + 1, + 2, + 3, + 4, + 5, + 0, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions_EditionDefault, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions_EditionDefault, _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(::google::protobuf::FieldOptions_EditionDefault, _impl_.edition_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions_EditionDefault, _impl_.value_), + 1, + 0, + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.ctype_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.packed_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.jstype_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.lazy_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.unverified_lazy_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.weak_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.debug_redact_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.retention_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.targets_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.edition_defaults_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldOptions, _impl_.uninterpreted_option_), + 1, + 3, + 2, + 4, + 5, + 6, + 7, + 8, + 9, + ~0u, + ~0u, + 0, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::OneofOptions, _impl_.uninterpreted_option_), + 0, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.allow_alias_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.deprecated_legacy_json_field_conflicts_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumOptions, _impl_.uninterpreted_option_), + 1, + 2, + 3, + 0, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.debug_redact_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.uninterpreted_option_), + 1, + 0, + 2, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_.uninterpreted_option_), + 0, + 1, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.idempotency_level_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.features_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::MethodOptions, _impl_.uninterpreted_option_), + 1, + 2, + 0, + ~0u, + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption_NamePart, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption_NamePart, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption_NamePart, _impl_.name_part_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption_NamePart, _impl_.is_extension_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.identifier_value_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.positive_int_value_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.negative_int_value_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.double_value_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.string_value_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::UninterpretedOption, _impl_.aggregate_value_), + ~0u, + 0, + 3, + 4, + 5, + 1, + 2, + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.field_presence_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.enum_type_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.repeated_field_encoding_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.utf8_validation_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.message_encoding_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSet, _impl_.json_format_), + 0, + 1, + 2, + 3, + 4, + 5, + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault, _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(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault, _impl_.edition_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault, _impl_.features_), + 1, + 0, + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults, _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(::google::protobuf::FeatureSetDefaults, _impl_.defaults_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults, _impl_.minimum_edition_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::FeatureSetDefaults, _impl_.maximum_edition_), + ~0u, + 0, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.path_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.span_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.leading_comments_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.trailing_comments_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo_Location, _impl_.leading_detached_comments_), + ~0u, + ~0u, + 0, + 1, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo, _impl_.location_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.path_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.source_file_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.begin_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.end_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::GeneratedCodeInfo_Annotation, _impl_.semantic_), + ~0u, + 0, + 1, + 2, + 3, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::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(::google::protobuf::GeneratedCodeInfo, _impl_.annotation_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, -1, -1, sizeof(::google::protobuf::FileDescriptorSet)}, {9, 30, -1, sizeof(::google::protobuf::FileDescriptorProto)}, {43, 54, -1, sizeof(::google::protobuf::DescriptorProto_ExtensionRange)}, @@ -1658,7 +1659,8 @@ static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_GeneratedCodeInfo_Annotation_default_instance_._instance, &::google::protobuf::_GeneratedCodeInfo_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n google/protobuf/descriptor.proto\022\017goog" "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file" "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" @@ -2394,6 +2396,16 @@ inline void FileDescriptorSet::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FileDescriptorSet::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FileDescriptorSet::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FileDescriptorSet::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -2482,13 +2494,6 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> FileDescriptorSet::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FileDescriptorSet::_class_data_ = { - FileDescriptorSet::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FileDescriptorSet::GetClassData() const { - return &_class_data_; -} void FileDescriptorSet::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -2645,6 +2650,16 @@ inline void FileDescriptorProto::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FileDescriptorProto::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FileDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FileDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -3023,13 +3038,6 @@ constexpr ::_pbi::TcParseTable<4, 13, 7, 79, 2> FileDescriptorProto::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FileDescriptorProto::_class_data_ = { - FileDescriptorProto::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FileDescriptorProto::GetClassData() const { - return &_class_data_; -} void FileDescriptorProto::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -3212,6 +3220,16 @@ inline void DescriptorProto_ExtensionRange::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +DescriptorProto_ExtensionRange::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + DescriptorProto_ExtensionRange::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void DescriptorProto_ExtensionRange::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -3352,13 +3370,6 @@ constexpr ::_pbi::TcParseTable<2, 3, 1, 0, 2> DescriptorProto_ExtensionRange::_t return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData DescriptorProto_ExtensionRange::_class_data_ = { - DescriptorProto_ExtensionRange::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* DescriptorProto_ExtensionRange::GetClassData() const { - return &_class_data_; -} void DescriptorProto_ExtensionRange::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -3468,6 +3479,16 @@ inline void DescriptorProto_ReservedRange::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +DescriptorProto_ReservedRange::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + DescriptorProto_ReservedRange::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void DescriptorProto_ReservedRange::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -3584,13 +3605,6 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 0, 2> DescriptorProto_ReservedRange::_ta return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData DescriptorProto_ReservedRange::_class_data_ = { - DescriptorProto_ReservedRange::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* DescriptorProto_ReservedRange::GetClassData() const { - return &_class_data_; -} void DescriptorProto_ReservedRange::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -3729,6 +3743,16 @@ inline void DescriptorProto::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +DescriptorProto::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + DescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void DescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -4035,13 +4059,6 @@ constexpr ::_pbi::TcParseTable<4, 10, 8, 65, 2> DescriptorProto::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData DescriptorProto::_class_data_ = { - DescriptorProto::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* DescriptorProto::GetClassData() const { - return &_class_data_; -} void DescriptorProto::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -4215,6 +4232,16 @@ inline void ExtensionRangeOptions_Declaration::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +ExtensionRangeOptions_Declaration::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + ExtensionRangeOptions_Declaration::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void ExtensionRangeOptions_Declaration::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ExtensionRangeOptions.Declaration) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -4403,13 +4430,6 @@ constexpr ::_pbi::TcParseTable<3, 5, 0, 71, 2> ExtensionRangeOptions_Declaration return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData ExtensionRangeOptions_Declaration::_class_data_ = { - ExtensionRangeOptions_Declaration::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* ExtensionRangeOptions_Declaration::GetClassData() const { - return &_class_data_; -} void ExtensionRangeOptions_Declaration::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -4551,6 +4571,16 @@ inline void ExtensionRangeOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +ExtensionRangeOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + ExtensionRangeOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void ExtensionRangeOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ExtensionRangeOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -4725,13 +4755,6 @@ constexpr ::_pbi::TcParseTable<3, 4, 4, 0, 12> ExtensionRangeOptions::_table_ = return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData ExtensionRangeOptions::_class_data_ = { - ExtensionRangeOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* ExtensionRangeOptions::GetClassData() const { - return &_class_data_; -} void ExtensionRangeOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -4924,6 +4947,16 @@ inline void FieldDescriptorProto::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FieldDescriptorProto::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FieldDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FieldDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -5255,13 +5288,6 @@ constexpr ::_pbi::TcParseTable<4, 11, 3, 96, 2> FieldDescriptorProto::_table_ = return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FieldDescriptorProto::_class_data_ = { - FieldDescriptorProto::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FieldDescriptorProto::GetClassData() const { - return &_class_data_; -} void FieldDescriptorProto::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -5425,6 +5451,16 @@ inline void OneofDescriptorProto::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +OneofDescriptorProto::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + OneofDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void OneofDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -5549,13 +5585,6 @@ constexpr ::_pbi::TcParseTable<1, 2, 1, 49, 2> OneofDescriptorProto::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData OneofDescriptorProto::_class_data_ = { - OneofDescriptorProto::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* OneofDescriptorProto::GetClassData() const { - return &_class_data_; -} void OneofDescriptorProto::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -5659,6 +5688,16 @@ inline void EnumDescriptorProto_EnumReservedRange::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +EnumDescriptorProto_EnumReservedRange::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + EnumDescriptorProto_EnumReservedRange::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void EnumDescriptorProto_EnumReservedRange::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -5775,13 +5814,6 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 0, 2> EnumDescriptorProto_EnumReservedRa return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData EnumDescriptorProto_EnumReservedRange::_class_data_ = { - EnumDescriptorProto_EnumReservedRange::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* EnumDescriptorProto_EnumReservedRange::GetClassData() const { - return &_class_data_; -} void EnumDescriptorProto_EnumReservedRange::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -5910,6 +5942,16 @@ inline void EnumDescriptorProto::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +EnumDescriptorProto::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + EnumDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void EnumDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -6103,13 +6145,6 @@ constexpr ::_pbi::TcParseTable<3, 5, 3, 61, 2> EnumDescriptorProto::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData EnumDescriptorProto::_class_data_ = { - EnumDescriptorProto::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* EnumDescriptorProto::GetClassData() const { - return &_class_data_; -} void EnumDescriptorProto::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -6252,6 +6287,16 @@ inline void EnumValueDescriptorProto::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +EnumValueDescriptorProto::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + EnumValueDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void EnumValueDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -6397,13 +6442,6 @@ constexpr ::_pbi::TcParseTable<2, 3, 1, 53, 2> EnumValueDescriptorProto::_table_ return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData EnumValueDescriptorProto::_class_data_ = { - EnumValueDescriptorProto::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* EnumValueDescriptorProto::GetClassData() const { - return &_class_data_; -} void EnumValueDescriptorProto::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -6538,6 +6576,16 @@ inline void ServiceDescriptorProto::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +ServiceDescriptorProto::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + ServiceDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void ServiceDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -6685,13 +6733,6 @@ constexpr ::_pbi::TcParseTable<2, 3, 2, 51, 2> ServiceDescriptorProto::_table_ = return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData ServiceDescriptorProto::_class_data_ = { - ServiceDescriptorProto::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* ServiceDescriptorProto::GetClassData() const { - return &_class_data_; -} void ServiceDescriptorProto::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -6850,6 +6891,16 @@ inline void MethodDescriptorProto::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +MethodDescriptorProto::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + MethodDescriptorProto::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void MethodDescriptorProto::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -7063,13 +7114,6 @@ constexpr ::_pbi::TcParseTable<3, 6, 1, 71, 2> MethodDescriptorProto::_table_ = return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData MethodDescriptorProto::_class_data_ = { - MethodDescriptorProto::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* MethodDescriptorProto::GetClassData() const { - return &_class_data_; -} void MethodDescriptorProto::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -7316,6 +7360,16 @@ inline void FileOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FileOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FileOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FileOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -7889,13 +7943,6 @@ constexpr ::_pbi::TcParseTable<5, 22, 3, 202, 12> FileOptions::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FileOptions::_class_data_ = { - FileOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FileOptions::GetClassData() const { - return &_class_data_; -} void FileOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -8132,6 +8179,16 @@ inline void MessageOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +MessageOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + MessageOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void MessageOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -8350,13 +8407,6 @@ constexpr ::_pbi::TcParseTable<3, 7, 2, 0, 7> MessageOptions::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData MessageOptions::_class_data_ = { - MessageOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* MessageOptions::GetClassData() const { - return &_class_data_; -} void MessageOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -8497,6 +8547,16 @@ inline void FieldOptions_EditionDefault::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FieldOptions_EditionDefault::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FieldOptions_EditionDefault::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FieldOptions_EditionDefault::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions.EditionDefault) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -8616,13 +8676,6 @@ constexpr ::_pbi::TcParseTable<1, 2, 1, 57, 2> FieldOptions_EditionDefault::_tab return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FieldOptions_EditionDefault::_class_data_ = { - FieldOptions_EditionDefault::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FieldOptions_EditionDefault::GetClassData() const { - return &_class_data_; -} void FieldOptions_EditionDefault::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -8785,6 +8838,16 @@ inline void FieldOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FieldOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FieldOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FieldOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -9138,13 +9201,6 @@ constexpr ::_pbi::TcParseTable<4, 13, 7, 0, 7> FieldOptions::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FieldOptions::_class_data_ = { - FieldOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FieldOptions::GetClassData() const { - return &_class_data_; -} void FieldOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -9312,6 +9368,16 @@ inline void OneofOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +OneofOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + OneofOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void OneofOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -9438,13 +9504,6 @@ constexpr ::_pbi::TcParseTable<2, 2, 2, 0, 7> OneofOptions::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData OneofOptions::_class_data_ = { - OneofOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* OneofOptions::GetClassData() const { - return &_class_data_; -} void OneofOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -9589,6 +9648,16 @@ inline void EnumOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +EnumOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + EnumOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void EnumOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -9773,13 +9842,6 @@ constexpr ::_pbi::TcParseTable<3, 5, 2, 0, 7> EnumOptions::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData EnumOptions::_class_data_ = { - EnumOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* EnumOptions::GetClassData() const { - return &_class_data_; -} void EnumOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -9939,6 +10001,16 @@ inline void EnumValueOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +EnumValueOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + EnumValueOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void EnumValueOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -10108,13 +10180,6 @@ constexpr ::_pbi::TcParseTable<3, 4, 2, 0, 7> EnumValueOptions::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData EnumValueOptions::_class_data_ = { - EnumValueOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* EnumValueOptions::GetClassData() const { - return &_class_data_; -} void EnumValueOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -10262,6 +10327,16 @@ inline void ServiceOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +ServiceOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + ServiceOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void ServiceOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -10409,13 +10484,6 @@ constexpr ::_pbi::TcParseTable<2, 3, 2, 0, 12> ServiceOptions::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData ServiceOptions::_class_data_ = { - ServiceOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* ServiceOptions::GetClassData() const { - return &_class_data_; -} void ServiceOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -10569,6 +10637,16 @@ inline void MethodOptions::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +MethodOptions::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + MethodOptions::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void MethodOptions::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -10743,13 +10821,6 @@ constexpr ::_pbi::TcParseTable<3, 4, 3, 0, 12> MethodOptions::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData MethodOptions::_class_data_ = { - MethodOptions::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* MethodOptions::GetClassData() const { - return &_class_data_; -} void MethodOptions::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -10884,6 +10955,16 @@ inline void UninterpretedOption_NamePart::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +UninterpretedOption_NamePart::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + UninterpretedOption_NamePart::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void UninterpretedOption_NamePart::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -11002,13 +11083,6 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 62, 2> UninterpretedOption_NamePart::_ta return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData UninterpretedOption_NamePart::_class_data_ = { - UninterpretedOption_NamePart::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* UninterpretedOption_NamePart::GetClassData() const { - return &_class_data_; -} void UninterpretedOption_NamePart::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -11155,6 +11229,16 @@ inline void UninterpretedOption::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +UninterpretedOption::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + UninterpretedOption::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void UninterpretedOption::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -11384,13 +11468,6 @@ constexpr ::_pbi::TcParseTable<3, 7, 1, 75, 2> UninterpretedOption::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData UninterpretedOption::_class_data_ = { - UninterpretedOption::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* UninterpretedOption::GetClassData() const { - return &_class_data_; -} void UninterpretedOption::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -11550,6 +11627,16 @@ inline void FeatureSet::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FeatureSet::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FeatureSet::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FeatureSet::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FeatureSet) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -11755,13 +11842,6 @@ constexpr ::_pbi::TcParseTable<3, 6, 6, 0, 2> FeatureSet::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FeatureSet::_class_data_ = { - FeatureSet::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FeatureSet::GetClassData() const { - return &_class_data_; -} void FeatureSet::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -11904,6 +11984,16 @@ inline void FeatureSetDefaults_FeatureSetEditionDefault::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FeatureSetDefaults_FeatureSetEditionDefault::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FeatureSetDefaults_FeatureSetEditionDefault::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FeatureSetDefaults_FeatureSetEditionDefault::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -12021,13 +12111,6 @@ constexpr ::_pbi::TcParseTable<1, 2, 2, 0, 2> FeatureSetDefaults_FeatureSetEditi return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FeatureSetDefaults_FeatureSetEditionDefault::_class_data_ = { - FeatureSetDefaults_FeatureSetEditionDefault::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FeatureSetDefaults_FeatureSetEditionDefault::GetClassData() const { - return &_class_data_; -} void FeatureSetDefaults_FeatureSetEditionDefault::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -12156,6 +12239,16 @@ inline void FeatureSetDefaults::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FeatureSetDefaults::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FeatureSetDefaults::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FeatureSetDefaults::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FeatureSetDefaults) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -12292,13 +12385,6 @@ constexpr ::_pbi::TcParseTable<1, 3, 3, 0, 2> FeatureSetDefaults::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FeatureSetDefaults::_class_data_ = { - FeatureSetDefaults::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FeatureSetDefaults::GetClassData() const { - return &_class_data_; -} void FeatureSetDefaults::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -12429,6 +12515,16 @@ inline void SourceCodeInfo_Location::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +SourceCodeInfo_Location::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + SourceCodeInfo_Location::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void SourceCodeInfo_Location::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -12637,13 +12733,6 @@ constexpr ::_pbi::TcParseTable<3, 5, 0, 106, 2> SourceCodeInfo_Location::_table_ return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData SourceCodeInfo_Location::_class_data_ = { - SourceCodeInfo_Location::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* SourceCodeInfo_Location::GetClassData() const { - return &_class_data_; -} void SourceCodeInfo_Location::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -12748,6 +12837,16 @@ inline void SourceCodeInfo::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +SourceCodeInfo::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + SourceCodeInfo::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void SourceCodeInfo::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -12836,13 +12935,6 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> SourceCodeInfo::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData SourceCodeInfo::_class_data_ = { - SourceCodeInfo::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* SourceCodeInfo::GetClassData() const { - return &_class_data_; -} void SourceCodeInfo::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -12964,6 +13056,16 @@ inline void GeneratedCodeInfo_Annotation::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +GeneratedCodeInfo_Annotation::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + GeneratedCodeInfo_Annotation::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void GeneratedCodeInfo_Annotation::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -13157,13 +13259,6 @@ constexpr ::_pbi::TcParseTable<3, 5, 1, 64, 2> GeneratedCodeInfo_Annotation::_ta return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData GeneratedCodeInfo_Annotation::_class_data_ = { - GeneratedCodeInfo_Annotation::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* GeneratedCodeInfo_Annotation::GetClassData() const { - return &_class_data_; -} void GeneratedCodeInfo_Annotation::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -13276,6 +13371,16 @@ inline void GeneratedCodeInfo::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +GeneratedCodeInfo::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + GeneratedCodeInfo::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void GeneratedCodeInfo::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -13364,13 +13469,6 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> GeneratedCodeInfo::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData GeneratedCodeInfo::_class_data_ = { - GeneratedCodeInfo::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* GeneratedCodeInfo::GetClassData() const { - return &_class_data_; -} void GeneratedCodeInfo::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 36220fdc97..d69623bb21 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -799,7 +799,7 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -822,11 +822,9 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : protected: explicit UninterpretedOption_NamePart(::google::protobuf::Arena* arena); UninterpretedOption_NamePart(::google::protobuf::Arena* arena, const UninterpretedOption_NamePart& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -995,7 +993,7 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1018,11 +1016,9 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : protected: explicit SourceCodeInfo_Location(::google::protobuf::Arena* arena); SourceCodeInfo_Location(::google::protobuf::Arena* arena, const SourceCodeInfo_Location& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1269,7 +1265,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1292,11 +1288,9 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : protected: explicit GeneratedCodeInfo_Annotation(::google::protobuf::Arena* arena); GeneratedCodeInfo_Annotation(::google::protobuf::Arena* arena, const GeneratedCodeInfo_Annotation& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1533,7 +1527,7 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1556,11 +1550,9 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : protected: explicit FieldOptions_EditionDefault(::google::protobuf::Arena* arena); FieldOptions_EditionDefault(::google::protobuf::Arena* arena, const FieldOptions_EditionDefault& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1729,7 +1721,7 @@ class PROTOBUF_EXPORT FeatureSet final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1752,11 +1744,9 @@ class PROTOBUF_EXPORT FeatureSet final : protected: explicit FeatureSet(::google::protobuf::Arena* arena); FeatureSet(::google::protobuf::Arena* arena, const FeatureSet& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -2277,7 +2267,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -2300,11 +2290,9 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : protected: explicit ExtensionRangeOptions_Declaration(::google::protobuf::Arena* arena); ExtensionRangeOptions_Declaration(::google::protobuf::Arena* arena, const ExtensionRangeOptions_Declaration& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -2518,7 +2506,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -2541,11 +2529,9 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : protected: explicit EnumDescriptorProto_EnumReservedRange(::google::protobuf::Arena* arena); EnumDescriptorProto_EnumReservedRange(::google::protobuf::Arena* arena, const EnumDescriptorProto_EnumReservedRange& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -2708,7 +2694,7 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -2731,11 +2717,9 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : protected: explicit DescriptorProto_ReservedRange(::google::protobuf::Arena* arena); DescriptorProto_ReservedRange(::google::protobuf::Arena* arena, const DescriptorProto_ReservedRange& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -2898,7 +2882,7 @@ class PROTOBUF_EXPORT UninterpretedOption final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -2921,11 +2905,9 @@ class PROTOBUF_EXPORT UninterpretedOption final : protected: explicit UninterpretedOption(::google::protobuf::Arena* arena); UninterpretedOption(::google::protobuf::Arena* arena, const UninterpretedOption& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -3180,7 +3162,7 @@ class PROTOBUF_EXPORT SourceCodeInfo final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -3203,11 +3185,9 @@ class PROTOBUF_EXPORT SourceCodeInfo final : protected: explicit SourceCodeInfo(::google::protobuf::Arena* arena); SourceCodeInfo(::google::protobuf::Arena* arena, const SourceCodeInfo& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -3365,7 +3345,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -3388,11 +3368,9 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : protected: explicit GeneratedCodeInfo(::google::protobuf::Arena* arena); GeneratedCodeInfo(::google::protobuf::Arena* arena, const GeneratedCodeInfo& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -3550,7 +3528,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -3573,11 +3551,9 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : protected: explicit FeatureSetDefaults_FeatureSetEditionDefault(::google::protobuf::Arena* arena); FeatureSetDefaults_FeatureSetEditionDefault(::google::protobuf::Arena* arena, const FeatureSetDefaults_FeatureSetEditionDefault& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -3744,7 +3720,7 @@ class PROTOBUF_EXPORT ServiceOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -3767,11 +3743,9 @@ class PROTOBUF_EXPORT ServiceOptions final : protected: explicit ServiceOptions(::google::protobuf::Arena* arena); ServiceOptions(::google::protobuf::Arena* arena, const ServiceOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -4137,7 +4111,7 @@ class PROTOBUF_EXPORT OneofOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -4160,11 +4134,9 @@ class PROTOBUF_EXPORT OneofOptions final : protected: explicit OneofOptions(::google::protobuf::Arena* arena); OneofOptions(::google::protobuf::Arena* arena, const OneofOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -4517,7 +4489,7 @@ class PROTOBUF_EXPORT MethodOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -4540,11 +4512,9 @@ class PROTOBUF_EXPORT MethodOptions final : protected: explicit MethodOptions(::google::protobuf::Arena* arena); MethodOptions(::google::protobuf::Arena* arena, const MethodOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -4944,7 +4914,7 @@ class PROTOBUF_EXPORT MessageOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -4967,11 +4937,9 @@ class PROTOBUF_EXPORT MessageOptions final : protected: explicit MessageOptions(::google::protobuf::Arena* arena); MessageOptions(::google::protobuf::Arena* arena, const MessageOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -5389,7 +5357,7 @@ class PROTOBUF_EXPORT FileOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -5412,11 +5380,9 @@ class PROTOBUF_EXPORT FileOptions final : protected: explicit FileOptions(::google::protobuf::Arena* arena); FileOptions(::google::protobuf::Arena* arena, const FileOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -6110,7 +6076,7 @@ class PROTOBUF_EXPORT FieldOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -6133,11 +6099,9 @@ class PROTOBUF_EXPORT FieldOptions final : protected: explicit FieldOptions(::google::protobuf::Arena* arena); FieldOptions(::google::protobuf::Arena* arena, const FieldOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -6741,7 +6705,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -6764,11 +6728,9 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : protected: explicit FeatureSetDefaults(::google::protobuf::Arena* arena); FeatureSetDefaults(::google::protobuf::Arena* arena, const FeatureSetDefaults& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -6953,7 +6915,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -6976,11 +6938,9 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : protected: explicit ExtensionRangeOptions(::google::protobuf::Arena* arena); ExtensionRangeOptions(::google::protobuf::Arena* arena, const ExtensionRangeOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -7388,7 +7348,7 @@ class PROTOBUF_EXPORT EnumValueOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -7411,11 +7371,9 @@ class PROTOBUF_EXPORT EnumValueOptions final : protected: explicit EnumValueOptions(::google::protobuf::Arena* arena); EnumValueOptions(::google::protobuf::Arena* arena, const EnumValueOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -7794,7 +7752,7 @@ class PROTOBUF_EXPORT EnumOptions final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -7817,11 +7775,9 @@ class PROTOBUF_EXPORT EnumOptions final : protected: explicit EnumOptions(::google::protobuf::Arena* arena); EnumOptions(::google::protobuf::Arena* arena, const EnumOptions& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -8213,7 +8169,7 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -8236,11 +8192,9 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : protected: explicit OneofDescriptorProto(::google::protobuf::Arena* arena); OneofDescriptorProto(::google::protobuf::Arena* arena, const OneofDescriptorProto& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -8413,7 +8367,7 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -8436,11 +8390,9 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : protected: explicit MethodDescriptorProto(::google::protobuf::Arena* arena); MethodDescriptorProto(::google::protobuf::Arena* arena, const MethodDescriptorProto& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -8677,7 +8629,7 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -8700,11 +8652,9 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : protected: explicit FieldDescriptorProto(::google::protobuf::Arena* arena); FieldDescriptorProto(::google::protobuf::Arena* arena, const FieldDescriptorProto& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -9075,7 +9025,7 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -9098,11 +9048,9 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : protected: explicit EnumValueDescriptorProto(::google::protobuf::Arena* arena); EnumValueDescriptorProto(::google::protobuf::Arena* arena, const EnumValueDescriptorProto& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -9288,7 +9236,7 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -9311,11 +9259,9 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : protected: explicit DescriptorProto_ExtensionRange(::google::protobuf::Arena* arena); DescriptorProto_ExtensionRange(::google::protobuf::Arena* arena, const DescriptorProto_ExtensionRange& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -9495,7 +9441,7 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -9518,11 +9464,9 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : protected: explicit ServiceDescriptorProto(::google::protobuf::Arena* arena); ServiceDescriptorProto(::google::protobuf::Arena* arena, const ServiceDescriptorProto& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -9715,7 +9659,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -9738,11 +9682,9 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : protected: explicit EnumDescriptorProto(::google::protobuf::Arena* arena); EnumDescriptorProto(::google::protobuf::Arena* arena, const EnumDescriptorProto& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -9987,7 +9929,7 @@ class PROTOBUF_EXPORT DescriptorProto final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -10010,11 +9952,9 @@ class PROTOBUF_EXPORT DescriptorProto final : protected: explicit DescriptorProto(::google::protobuf::Arena* arena); DescriptorProto(::google::protobuf::Arena* arena, const DescriptorProto& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -10360,7 +10300,7 @@ class PROTOBUF_EXPORT FileDescriptorProto final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -10383,11 +10323,9 @@ class PROTOBUF_EXPORT FileDescriptorProto final : protected: explicit FileDescriptorProto(::google::protobuf::Arena* arena); FileDescriptorProto(::google::protobuf::Arena* arena, const FileDescriptorProto& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -10778,7 +10716,7 @@ class PROTOBUF_EXPORT FileDescriptorSet final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -10801,11 +10739,9 @@ class PROTOBUF_EXPORT FileDescriptorSet final : protected: explicit FileDescriptorSet(::google::protobuf::Arena* arena); FileDescriptorSet(::google::protobuf::Arena* arena, const FileDescriptorSet& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -11541,11 +11477,11 @@ inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileO ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FileOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FileOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -11637,11 +11573,11 @@ inline void FileDescriptorProto::set_allocated_source_code_info(::google::protob ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::SourceCodeInfo*>(_impl_.source_code_info_); + delete (_impl_.source_code_info_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::SourceCodeInfo*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -11893,11 +11829,11 @@ inline void DescriptorProto_ExtensionRange::set_allocated_options(::google::prot ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::ExtensionRangeOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::ExtensionRangeOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -12418,11 +12354,11 @@ inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOp ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::MessageOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::MessageOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -12996,11 +12932,11 @@ inline void ExtensionRangeOptions::set_allocated_features(::google::protobuf::Fe ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -13594,11 +13530,11 @@ inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::Fiel ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FieldOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FieldOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -13793,11 +13729,11 @@ inline void OneofDescriptorProto::set_allocated_options(::google::protobuf::Oneo ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::OneofOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::OneofOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -14073,11 +14009,11 @@ inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumO ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::EnumOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::EnumOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -14422,11 +14358,11 @@ inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf:: ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::EnumValueOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::EnumValueOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -14642,11 +14578,11 @@ inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::Se ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::ServiceOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::ServiceOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -14955,11 +14891,11 @@ inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::Met ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::MethodOptions*>(_impl_.options_); + delete (_impl_.options_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::MethodOptions*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -16102,11 +16038,11 @@ inline void FileOptions::set_allocated_features(::google::protobuf::FeatureSet* ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -16391,11 +16327,11 @@ inline void MessageOptions::set_allocated_features(::google::protobuf::FeatureSe ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -16994,11 +16930,11 @@ inline void FieldOptions::set_allocated_features(::google::protobuf::FeatureSet* ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -17143,11 +17079,11 @@ inline void OneofOptions::set_allocated_features(::google::protobuf::FeatureSet* ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -17376,11 +17312,11 @@ inline void EnumOptions::set_allocated_features(::google::protobuf::FeatureSet* ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -17553,11 +17489,11 @@ inline void EnumValueOptions::set_allocated_features(::google::protobuf::Feature ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -17730,11 +17666,11 @@ inline void ServiceOptions::set_allocated_features(::google::protobuf::FeatureSe ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -17964,11 +17900,11 @@ inline void MethodOptions::set_allocated_features(::google::protobuf::FeatureSet ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } @@ -18773,11 +18709,11 @@ inline void FeatureSetDefaults_FeatureSetEditionDefault::set_allocated_features( ::google::protobuf::Arena* message_arena = GetArena(); PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); if (message_arena == nullptr) { - delete reinterpret_cast<::google::protobuf::FeatureSet*>(_impl_.features_); + delete (_impl_.features_); } if (value != nullptr) { - ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::FeatureSet*>(value)->GetArena(); + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } diff --git a/src/google/protobuf/descriptor_lite.h b/src/google/protobuf/descriptor_lite.h new file mode 100644 index 0000000000..db5805affe --- /dev/null +++ b/src/google/protobuf/descriptor_lite.h @@ -0,0 +1,87 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd +// +// This file contains definitions for the descriptors, so they can be used +// without importing descriptor.h + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_LITE_H__ +#define GOOGLE_PROTOBUF_DESCRIPTOR_LITE_H__ + +namespace google { +namespace protobuf { +namespace internal { + +class FieldDescriptorLite { + public: + // 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 { + TYPE_DOUBLE = 1, // double, exactly eight bytes on the wire. + TYPE_FLOAT = 2, // float, exactly four bytes on the wire. + TYPE_INT64 = 3, // int64, varint on the wire. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4, // uint64, varint on the wire. + TYPE_INT32 = 5, // int32, varint on the wire. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6, // uint64, exactly eight bytes on the wire. + TYPE_FIXED32 = 7, // uint32, exactly four bytes on the wire. + TYPE_BOOL = 8, // bool, varint on the wire. + TYPE_STRING = 9, // UTF-8 text. + TYPE_GROUP = 10, // Tag-delimited message. Deprecated. + TYPE_MESSAGE = 11, // Length-delimited message. + + TYPE_BYTES = 12, // Arbitrary byte array. + TYPE_UINT32 = 13, // uint32, varint on the wire + TYPE_ENUM = 14, // Enum, varint on the wire + TYPE_SFIXED32 = 15, // int32, exactly four bytes on the wire + TYPE_SFIXED64 = 16, // int64, exactly eight bytes on the wire + TYPE_SINT32 = 17, // int32, ZigZag-encoded varint on the wire + TYPE_SINT64 = 18, // int64, ZigZag-encoded varint on the wire + + MAX_TYPE = 18, // Constant useful for defining lookup tables + // indexed by Type. + }; + + // Specifies the C++ data type used to represent the field. There is a + // fixed mapping from Type to CppType where each Type maps to exactly one + // CppType. 0 is reserved for errors. + enum CppType { + CPPTYPE_INT32 = 1, // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32 + CPPTYPE_INT64 = 2, // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64 + CPPTYPE_UINT32 = 3, // TYPE_UINT32, TYPE_FIXED32 + CPPTYPE_UINT64 = 4, // TYPE_UINT64, TYPE_FIXED64 + CPPTYPE_DOUBLE = 5, // TYPE_DOUBLE + CPPTYPE_FLOAT = 6, // TYPE_FLOAT + CPPTYPE_BOOL = 7, // TYPE_BOOL + CPPTYPE_ENUM = 8, // TYPE_ENUM + CPPTYPE_STRING = 9, // TYPE_STRING, TYPE_BYTES + CPPTYPE_MESSAGE = 10, // TYPE_MESSAGE, TYPE_GROUP + + MAX_CPPTYPE = 10, // Constant useful for defining lookup tables + // indexed by CppType. + }; + + // Identifies whether the field is optional, required, or repeated. 0 is + // reserved for errors. + enum Label { + LABEL_OPTIONAL = 1, // optional + LABEL_REQUIRED = 2, // required + LABEL_REPEATED = 3, // repeated + + MAX_LABEL = 3, // Constant useful for defining lookup tables + // indexed by Label. + }; +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_DESCRIPTOR_LITE_H__ diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 8986cf095d..01dc123a83 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -7217,6 +7217,13 @@ TEST_F(ValidationErrorTest, UnusedImportWithOtherError) { "foo.proto: Foo.foo: EXTENDEE: \"Baz\" is not defined.\n"); } +TEST(EditionsTest, DenseRange) { + for (int i = static_cast(PROTOBUF_MINIMUM_EDITION); + i <= static_cast(PROTOBUF_MAXIMUM_EDITION); ++i) { + EXPECT_TRUE(Edition_IsValid(i)); + } +} + using FeaturesBaseTest = ValidationErrorTest; class FeaturesTest : public FeaturesBaseTest { @@ -9258,7 +9265,7 @@ TEST_F(FeaturesTest, FeaturesOutsideEditions) { "editions.\n"); } -TEST_F(FeaturesTest, InvalidRequiredByDefault) { +TEST_F(FeaturesTest, InvalidFileRequiredPresence) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( R"pb( @@ -9270,6 +9277,31 @@ TEST_F(FeaturesTest, InvalidRequiredByDefault) { "foo.proto: foo.proto: EDITIONS: Required presence can't be specified " "by default.\n"); } + +TEST_F(FeaturesTest, InvalidFileJavaStringCheckUtf8) { + BuildDescriptorMessagesInTestPool(); + BuildFileWithErrors( + R"pb( + name: "foo.proto" + syntax: "editions" + edition: EDITION_2023 + options { java_string_check_utf8: true } + )pb", + "foo.proto: foo.proto: EDITIONS: File option java_string_check_utf8 is " + "not allowed under editions. Use the (pb.java).utf8_validation feature " + "to control this behavior.\n"); +} + +TEST_F(FeaturesTest, Proto2FileJavaStringCheckUtf8) { + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* file = BuildFile( + R"pb( + name: "foo.proto" + syntax: "proto2" + options { java_string_check_utf8: true } + )pb"); + EXPECT_EQ(file->options().java_string_check_utf8(), true); +} TEST_F(FeaturesTest, InvalidFieldPacked) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index 832aae80e1..a3838bdfa3 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -49,29 +49,31 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fduration_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _impl_.seconds_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _impl_.nanos_), +const ::uint32_t + TableStruct_google_2fprotobuf_2fduration_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _impl_.seconds_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _impl_.nanos_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, -1, -1, sizeof(::google::protobuf::Duration)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Duration_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\036google/protobuf/duration.proto\022\017google" ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r" "\n\005nanos\030\002 \001(\005B\203\001\n\023com.google.protobufB\rD" @@ -157,6 +159,16 @@ inline void Duration::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Duration::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Duration::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Duration::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Duration) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -266,13 +278,6 @@ const ::_pbi::TcParseTable<1, 2, 0, 0, 2> Duration::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Duration::_class_data_ = { - Duration::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Duration::GetClassData() const { - return &_class_data_; -} void Duration::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h index 3ed09becbb..44d9a0886e 100644 --- a/src/google/protobuf/duration.pb.h +++ b/src/google/protobuf/duration.pb.h @@ -168,7 +168,7 @@ class PROTOBUF_EXPORT Duration final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -191,11 +191,9 @@ class PROTOBUF_EXPORT Duration final : protected: explicit Duration(::google::protobuf::Arena* arena); Duration(::google::protobuf::Arena* arena, const Duration& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/editions/BUILD b/src/google/protobuf/editions/BUILD index 04e1967ac1..4489ffdbf8 100644 --- a/src/google/protobuf/editions/BUILD +++ b/src/google/protobuf/editions/BUILD @@ -1,22 +1,107 @@ load("@rules_cc//cc:defs.bzl", "cc_proto_library") +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load(":defaults.bzl", "compile_edition_defaults", "embed_edition_defaults") + +bzl_library( + name = "defaults", + srcs = ["defaults.bzl"], + visibility = ["//visibility:public"], +) + +compile_edition_defaults( + name = "test_defaults_2023", + testonly = True, + srcs = ["//src/google/protobuf:unittest_features_proto"], + maximum_edition = "2023", + minimum_edition = "2023", +) + +compile_edition_defaults( + name = "test_defaults_future", + testonly = True, + srcs = ["//src/google/protobuf:unittest_features_proto"], + maximum_edition = "99997_TEST_ONLY", + minimum_edition = "2023", +) + +compile_edition_defaults( + name = "test_defaults_far_future", + testonly = True, + srcs = ["//src/google/protobuf:unittest_features_proto"], + maximum_edition = "99999_TEST_ONLY", + minimum_edition = "99997_TEST_ONLY", +) + +embed_edition_defaults( + name = "embed_test_defaults", + testonly = True, + defaults = ":test_defaults_2023", + output = "defaults_test_embedded.h", + placeholder = "DEFAULTS_VALUE", + template = "defaults_test_embedded.h.template", +) + +cc_binary( + name = "internal_defaults_escape", + srcs = ["internal_defaults_escape.cc"], + # This needs to be public for users of embed_edition_defaults. + visibility = ["//visibility:public"], + deps = [ + "//src/google/protobuf", + "@com_google_absl//absl/strings", + ], +) + +cc_library( + name = "defaults_test_embedded", + hdrs = [ + "defaults_test_embedded.h", + ], + strip_include_prefix = "/src", +) + +cc_test( + name = "defaults_test", + srcs = ["defaults_test.cc"], + data = [ + ":test_defaults_2023", + ":test_defaults_far_future", + ":test_defaults_future", + ], + deps = [ + ":defaults_test_embedded", + "//src/google/protobuf", + "//src/google/protobuf:unittest_features_cc_proto", + "//src/google/protobuf/stubs", + "//src/google/protobuf/testing", + "@bazel_tools//tools/cpp/runfiles", + "@com_google_absl//absl/memory", + "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:string_view", + "@com_google_googletest//:gtest_main", + ], +) proto_library( - name = "test_messages_proto2_proto", + name = "test_messages_proto2_editions_proto", testonly = True, - srcs = ["golden/test_messages_proto2.proto"], + srcs = ["golden/test_messages_proto2_editions.proto"], strip_import_prefix = "/src", ) cc_proto_library( - name = "test_messages_proto2_cc_proto", + name = "test_messages_proto2_editions_cc_proto", testonly = True, - deps = [":test_messages_proto2_proto"], + visibility = ["//conformance:__pkg__"], + deps = [":test_messages_proto2_editions_proto"], ) proto_library( - name = "test_messages_proto3_proto", + name = "test_messages_proto3_editions_proto", testonly = True, - srcs = ["golden/test_messages_proto3.proto"], + srcs = ["golden/test_messages_proto3_editions.proto"], strip_import_prefix = "/src", deps = [ "//:any_proto", @@ -29,9 +114,10 @@ proto_library( ) cc_proto_library( - name = "test_messages_proto3_cc_proto", + name = "test_messages_proto3_editions_cc_proto", testonly = True, - deps = [":test_messages_proto3_proto"], + visibility = ["//conformance:__pkg__"], + deps = [":test_messages_proto3_editions_proto"], ) proto_library( @@ -52,8 +138,8 @@ cc_test( srcs = ["generated_files_test.cc"], deps = [ ":test_editions_default_features_cc_proto", - ":test_messages_proto2_cc_proto", - ":test_messages_proto3_cc_proto", + ":test_messages_proto2_editions_cc_proto", + ":test_messages_proto3_editions_cc_proto", "//:protobuf", "//src/google/protobuf:test_textproto", "@com_google_googletest//:gtest_main", @@ -64,7 +150,7 @@ cc_test( name = "generated_reflection_test", srcs = ["generated_reflection_test.cc"], deps = [ - ":test_messages_proto2_cc_proto", + ":test_messages_proto2_editions_cc_proto", "@com_google_googletest//:gtest_main", ], ) diff --git a/src/google/protobuf/editions/defaults.bzl b/src/google/protobuf/editions/defaults.bzl new file mode 100644 index 0000000000..865efaf705 --- /dev/null +++ b/src/google/protobuf/editions/defaults.bzl @@ -0,0 +1,112 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2023 Google Inc. All rights reserved. +# +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file or at +# https://developers.google.com/open-source/licenses/bsd + +""" +Provide a rule for generating the intermediate feature set defaults used for feature resolution. + +See go/life-of-a-featureset for more information. +""" + +def _compile_edition_defaults_impl(ctx): + out_file = ctx.actions.declare_file(ctx.outputs.output.basename) + sources = [] + paths = [] + for src in ctx.attr.srcs: + sources.extend(src[ProtoInfo].transitive_sources.to_list()) + paths.extend(src[ProtoInfo].transitive_proto_path.to_list()) + + args = ctx.actions.args() + args.add("--experimental_edition_defaults_out", out_file) + + args.add("--experimental_edition_defaults_minimum", ctx.attr.minimum_edition) + args.add("--experimental_edition_defaults_maximum", ctx.attr.maximum_edition) + for p in paths: + args.add("--proto_path", p) + for source in sources: + args.add(source) + ctx.actions.run( + outputs = [out_file], + inputs = sources, + executable = ctx.executable._protoc, + arguments = [args], + progress_message = "Generating edition defaults", + ) + +compile_edition_defaults = rule( + attrs = { + "srcs": attr.label_list( + mandatory = True, + allow_rules = ["proto_library"], + providers = [ProtoInfo], + ), + "minimum_edition": attr.string(mandatory = True), + "maximum_edition": attr.string(mandatory = True), + "_protoc": attr.label( + default = "//src/google/protobuf/compiler:protoc_minimal", + executable = True, + cfg = "exec", + ), + }, + implementation = _compile_edition_defaults_impl, + outputs = { + "output": "%{name}.binpb", + }, +) + +def _embed_edition_defaults_impl(ctx): + ctx.actions.run_shell( + outputs = [ctx.outputs.output], + inputs = [ctx.file.defaults, ctx.file.template], + tools = [ctx.executable._escape], + command = """ + DEFAULTS_RAW=$({escape} < {defaults}) + # Windows requires extra escaping. + DEFAULTS_ESCAPED=$(echo $DEFAULTS_RAW | sed 's/\\\\/\\\\\\\\/g' || + echo $DEFAULTS_RAW | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g') + cp -f {template} {output} + # MacOS requires a backup file. + sed -i.bak \"s|{placeholder}|$DEFAULTS_ESCAPED|g\" {output} + """.format( + escape = ctx.executable._escape.path, + defaults = ctx.file.defaults.path, + template = ctx.file.template.path, + output = ctx.outputs.output.path, + placeholder = ctx.attr.placeholder, + ), + ) + +embed_edition_defaults = rule( + doc = "genrule to embed edition defaults binary data into a template file using octal C-style escaping.", + attrs = { + "defaults": attr.label( + mandatory = True, + allow_single_file = True, + allow_rules = ["compile_edition_defaults"], + providers = [ProtoInfo], + doc = "The compile_edition_defaults rule to embed", + ), + "output": attr.output( + mandatory = True, + doc = "The name of the output file", + ), + "template": attr.label( + mandatory = True, + allow_single_file = True, + doc = "The template to use for generating the output file", + ), + "placeholder": attr.string( + mandatory = True, + doc = "The placeholder to replace with a serialized string in the template", + ), + "_escape": attr.label( + default = "//src/google/protobuf/editions:internal_defaults_escape", + executable = True, + cfg = "exec", + ), + }, + implementation = _embed_edition_defaults_impl, +) diff --git a/src/google/protobuf/editions/defaults_test.cc b/src/google/protobuf/editions/defaults_test.cc new file mode 100644 index 0000000000..24c66ec6e9 --- /dev/null +++ b/src/google/protobuf/editions/defaults_test.cc @@ -0,0 +1,145 @@ +#include + +#include "tools/cpp/runfiles/runfiles.h" +#include "google/protobuf/testing/file.h" +#include "google/protobuf/testing/file.h" +#include "google/protobuf/descriptor.pb.h" +#include +#include +#include "absl/memory/memory.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/editions/defaults_test_embedded.h" +#include "google/protobuf/unittest_features.pb.h" +#include "google/protobuf/stubs/status_macros.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define ASSERT_OK(x) ASSERT_TRUE(x.ok()) << x.status().message(); + +namespace google { +namespace protobuf { +namespace { + +absl::StatusOr ReadDefaults(absl::string_view name) { + auto runfiles = absl::WrapUnique(bazel::tools::cpp::runfiles::Runfiles::CreateForTest()); + std::string file = runfiles->Rlocation(absl::StrCat( + "com_google_protobuf/src/google/protobuf/editions/", + name, ".binpb")); + std::string data; + RETURN_IF_ERROR(File::GetContents(file, &data, true)); + FeatureSetDefaults defaults; + if (!defaults.ParseFromString(data)) { + return absl::InternalError("Could not parse edition defaults!"); + } + return defaults; +} + +TEST(DefaultsTest, Check2023) { + auto defaults = ReadDefaults("test_defaults_2023"); + ASSERT_OK(defaults); + ASSERT_EQ(defaults->defaults().size(), 3); + ASSERT_EQ(defaults->minimum_edition(), EDITION_2023); + ASSERT_EQ(defaults->maximum_edition(), EDITION_2023); + + EXPECT_EQ(defaults->defaults()[0].edition(), EDITION_PROTO2); + EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); + EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); + EXPECT_EQ(defaults->defaults()[2].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[2] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 1); +} + +TEST(DefaultsTest, CheckFuture) { + auto defaults = ReadDefaults("test_defaults_future"); + ASSERT_OK(defaults); + ASSERT_EQ(defaults->defaults().size(), 4); + ASSERT_EQ(defaults->minimum_edition(), EDITION_2023); + ASSERT_EQ(defaults->maximum_edition(), EDITION_99997_TEST_ONLY); + + EXPECT_EQ(defaults->defaults()[0].edition(), EDITION_PROTO2); + EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); + EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); + EXPECT_EQ(defaults->defaults()[2].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[2] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 1); + EXPECT_EQ(defaults->defaults()[3].edition(), EDITION_99997_TEST_ONLY); + EXPECT_EQ(defaults->defaults()[3].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[3] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 2); +} + +TEST(DefaultsTest, CheckFarFuture) { + auto defaults = ReadDefaults("test_defaults_far_future"); + ASSERT_OK(defaults); + ASSERT_EQ(defaults->defaults().size(), 5); + ASSERT_EQ(defaults->minimum_edition(), EDITION_99997_TEST_ONLY); + ASSERT_EQ(defaults->maximum_edition(), EDITION_99999_TEST_ONLY); + + EXPECT_EQ(defaults->defaults()[0].edition(), EDITION_PROTO2); + EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); + EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); + EXPECT_EQ(defaults->defaults()[2].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[2] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 1); + EXPECT_EQ(defaults->defaults()[3].edition(), EDITION_99997_TEST_ONLY); + EXPECT_EQ(defaults->defaults()[3].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[3] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 2); + EXPECT_EQ(defaults->defaults()[4].edition(), EDITION_99998_TEST_ONLY); + EXPECT_EQ(defaults->defaults()[4].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[4] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 3); +} + +TEST(DefaultsTest, Embedded) { + FeatureSetDefaults defaults; + ASSERT_TRUE(defaults.ParseFromArray(DEFAULTS_TEST_EMBEDDED, + sizeof(DEFAULTS_TEST_EMBEDDED) - 1)) + << "Could not parse embedded data"; + ASSERT_EQ(defaults.defaults().size(), 3); + ASSERT_EQ(defaults.minimum_edition(), EDITION_2023); + ASSERT_EQ(defaults.maximum_edition(), EDITION_2023); + + EXPECT_EQ(defaults.defaults()[0].edition(), EDITION_PROTO2); + EXPECT_EQ(defaults.defaults()[1].edition(), EDITION_PROTO3); + EXPECT_EQ(defaults.defaults()[2].edition(), EDITION_2023); + EXPECT_EQ(defaults.defaults()[2].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults.defaults()[2] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 1); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/editions/generated_files_test.cc b/src/google/protobuf/editions/generated_files_test.cc index f74aa977e9..fe2bf0f142 100644 --- a/src/google/protobuf/editions/generated_files_test.cc +++ b/src/google/protobuf/editions/generated_files_test.cc @@ -9,8 +9,8 @@ #include #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/editions/golden/test_messages_proto2.pb.h" -#include "google/protobuf/editions/golden/test_messages_proto3.pb.h" +#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h" +#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h" #include "google/protobuf/editions/proto/test_editions_default_features.pb.h" #include "google/protobuf/test_textproto.h" @@ -22,9 +22,9 @@ namespace protobuf { namespace { using ::protobuf_editions_test::EditionsDefaultMessage; -using ::protobuf_test_messages::proto2::TestAllRequiredTypesProto2; -using ::protobuf_test_messages::proto2::TestAllTypesProto2; -using ::protobuf_test_messages::proto3::TestAllTypesProto3; +using ::protobuf_test_messages::editions::proto2::TestAllRequiredTypesProto2; +using ::protobuf_test_messages::editions::proto2::TestAllTypesProto2; +using ::protobuf_test_messages::editions::proto3::TestAllTypesProto3; using ::testing::NotNull; TEST(Generated, Parsing) { diff --git a/src/google/protobuf/editions/generated_reflection_test.cc b/src/google/protobuf/editions/generated_reflection_test.cc index ede6c6e845..a4161b9324 100644 --- a/src/google/protobuf/editions/generated_reflection_test.cc +++ b/src/google/protobuf/editions/generated_reflection_test.cc @@ -6,13 +6,13 @@ // https://developers.google.com/open-source/licenses/bsd #include -#include "google/protobuf/editions/golden/test_messages_proto2.pb.h" +#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h" namespace google { namespace protobuf { namespace { -using ::protobuf_test_messages::proto2::TestAllTypesProto2; +using ::protobuf_test_messages::editions::proto2::TestAllTypesProto2; // It's important that no calls that would initialize the generated pool occur // in any tests in this file. This test guarantees that there's no mutex diff --git a/src/google/protobuf/editions/golden/editions_transform_proto2.proto b/src/google/protobuf/editions/golden/editions_transform_proto2.proto index d664bbc447..0c483d1db4 100644 --- a/src/google/protobuf/editions/golden/editions_transform_proto2.proto +++ b/src/google/protobuf/editions/golden/editions_transform_proto2.proto @@ -21,7 +21,6 @@ import "google/protobuf/editions/proto/editions_transform_proto3.proto"; option features.enum_type = CLOSED; option features.repeated_field_encoding = EXPANDED; option features.utf8_validation = NONE; -option features.json_format = LEGACY_BEST_EFFORT; option java_multiple_files = true; option cc_enable_arenas = true; diff --git a/src/google/protobuf/editions/golden/editions_transform_proto2_lite.proto b/src/google/protobuf/editions/golden/editions_transform_proto2_lite.proto index 125be83a0f..ca0d3d8bdc 100644 --- a/src/google/protobuf/editions/golden/editions_transform_proto2_lite.proto +++ b/src/google/protobuf/editions/golden/editions_transform_proto2_lite.proto @@ -9,10 +9,7 @@ edition = "2023"; package protobuf_editions_test; -option features.enum_type = CLOSED; -option features.repeated_field_encoding = EXPANDED; option features.utf8_validation = NONE; -option features.json_format = LEGACY_BEST_EFFORT; option optimize_for = LITE_RUNTIME; message TestMessageLite { diff --git a/src/google/protobuf/editions/golden/editions_transform_proto2_utf8_disabled.proto b/src/google/protobuf/editions/golden/editions_transform_proto2_utf8_disabled.proto index 9a7d0c54dc..b0a70863e8 100644 --- a/src/google/protobuf/editions/golden/editions_transform_proto2_utf8_disabled.proto +++ b/src/google/protobuf/editions/golden/editions_transform_proto2_utf8_disabled.proto @@ -9,10 +9,7 @@ edition = "2023"; package protobuf_editions_test; -option features.enum_type = CLOSED; -option features.repeated_field_encoding = EXPANDED; option features.utf8_validation = NONE; -option features.json_format = LEGACY_BEST_EFFORT; message TestMessageUtf8Disabled { string string_field = 1; diff --git a/src/google/protobuf/editions/golden/test_messages_proto2.proto b/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto similarity index 98% rename from src/google/protobuf/editions/golden/test_messages_proto2.proto rename to src/google/protobuf/editions/golden/test_messages_proto2_editions.proto index 32da3854c0..3d9e9adf6f 100644 --- a/src/google/protobuf/editions/golden/test_messages_proto2.proto +++ b/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto @@ -13,13 +13,12 @@ edition = "2023"; -package protobuf_test_messages.proto2; +package protobuf_test_messages.editions.proto2; option features.enum_type = CLOSED; option features.repeated_field_encoding = EXPANDED; option features.utf8_validation = NONE; -option features.json_format = LEGACY_BEST_EFFORT; -option java_package = "com.google.protobuf_test_messages.proto2"; +option java_package = "com.google.protobuf_test_messages.editions.proto2"; option objc_class_prefix = "Proto2"; // This is the default, but we specify it here explicitly. diff --git a/src/google/protobuf/editions/golden/test_messages_proto3.proto b/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto similarity index 98% rename from src/google/protobuf/editions/golden/test_messages_proto3.proto rename to src/google/protobuf/editions/golden/test_messages_proto3_editions.proto index be9ca144e4..9dbf63e6a5 100644 --- a/src/google/protobuf/editions/golden/test_messages_proto3.proto +++ b/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto @@ -13,7 +13,7 @@ edition = "2023"; -package protobuf_test_messages.proto3; +package protobuf_test_messages.editions.proto3; import "google/protobuf/any.proto"; import "google/protobuf/duration.proto"; @@ -23,7 +23,7 @@ import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; option features.field_presence = IMPLICIT; -option java_package = "com.google.protobuf_test_messages.proto3"; +option java_package = "com.google.protobuf_test_messages.editions.proto3"; option objc_class_prefix = "Proto3"; // This is the default, but we specify it here explicitly. diff --git a/src/google/protobuf/editions/internal_defaults_escape.cc b/src/google/protobuf/editions/internal_defaults_escape.cc new file mode 100644 index 0000000000..4c1aa469ec --- /dev/null +++ b/src/google/protobuf/editions/internal_defaults_escape.cc @@ -0,0 +1,35 @@ +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "google/protobuf/descriptor.pb.h" +#include "absl/strings/escaping.h" + +#if defined(_WIN32) +#include "google/protobuf/io/io_win32.h" + +// DO NOT include , instead create functions in io_win32.{h,cc} and import +// them like we do below. +using google::protobuf::io::win32::setmode; +#endif + +int main(int argc, char *argv[]) { +#ifdef _WIN32 + setmode(STDIN_FILENO, _O_BINARY); + setmode(STDOUT_FILENO, _O_BINARY); +#endif + google::protobuf::FeatureSetDefaults defaults; + if (!defaults.ParseFromFileDescriptor(STDIN_FILENO)) { + std::cerr << argv[0] << ": unable to parse edition defaults." << std::endl; + return 1; + } + std::string output; + defaults.SerializeToString(&output); + std::cout << absl::CEscape(output); + return 0; +} diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index f561752542..0601bb4064 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -41,27 +41,29 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fempty_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Empty, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) +const ::uint32_t + TableStruct_google_2fprotobuf_2fempty_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Empty, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, -1, -1, sizeof(::google::protobuf::Empty)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Empty_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\033google/protobuf/empty.proto\022\017google.pr" "otobuf\"\007\n\005EmptyB}\n\023com.google.protobufB\n" "EmptyProtoP\001Z.google.golang.org/protobuf" diff --git a/src/google/protobuf/endian.h b/src/google/protobuf/endian.h index 2c6e50cbe3..781954e499 100644 --- a/src/google/protobuf/endian.h +++ b/src/google/protobuf/endian.h @@ -65,7 +65,7 @@ inline uint16_t BSwap16(uint16_t host_int) { namespace little_endian { inline uint16_t FromHost(uint16_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return BSwap16(value); #else return value; @@ -73,7 +73,7 @@ inline uint16_t FromHost(uint16_t value) { } inline uint32_t FromHost(uint32_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return BSwap32(value); #else return value; @@ -81,7 +81,7 @@ inline uint32_t FromHost(uint32_t value) { } inline uint64_t FromHost(uint64_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return BSwap64(value); #else return value; @@ -89,7 +89,7 @@ inline uint64_t FromHost(uint64_t value) { } inline uint16_t ToHost(uint16_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return BSwap16(value); #else return value; @@ -97,7 +97,7 @@ inline uint16_t ToHost(uint16_t value) { } inline uint32_t ToHost(uint32_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return BSwap32(value); #else return value; @@ -105,7 +105,7 @@ inline uint32_t ToHost(uint32_t value) { } inline uint64_t ToHost(uint64_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return BSwap64(value); #else return value; @@ -117,7 +117,7 @@ inline uint64_t ToHost(uint64_t value) { namespace big_endian { inline uint16_t FromHost(uint16_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return value; #else return BSwap16(value); @@ -125,7 +125,7 @@ inline uint16_t FromHost(uint16_t value) { } inline uint32_t FromHost(uint32_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return value; #else return BSwap32(value); @@ -133,7 +133,7 @@ inline uint32_t FromHost(uint32_t value) { } inline uint64_t FromHost(uint64_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return value; #else return BSwap64(value); @@ -141,7 +141,7 @@ inline uint64_t FromHost(uint64_t value) { } inline uint16_t ToHost(uint16_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return value; #else return BSwap16(value); @@ -149,7 +149,7 @@ inline uint16_t ToHost(uint16_t value) { } inline uint32_t ToHost(uint32_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return value; #else return BSwap32(value); @@ -157,7 +157,7 @@ inline uint32_t ToHost(uint32_t value) { } inline uint64_t ToHost(uint64_t value) { -#if defined(PROTOBUF_BIG_ENDIAN) +#if defined(ABSL_IS_BIG_ENDIAN) return value; #else return BSwap64(value); diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 4b54d7a3b6..7fde2cf8de 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -11,6 +11,7 @@ #include "google/protobuf/extension_set.h" +#include #include #include #include @@ -1933,6 +1934,8 @@ LazyEagerVerifyFnType FindExtensionLazyEagerVerifyFn( return nullptr; } +std::atomic + ExtensionSet::maybe_create_lazy_extension_; } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index f45a1c858c..dd4a473ebc 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -16,6 +16,7 @@ #define GOOGLE_PROTOBUF_EXTENSION_SET_H__ #include +#include #include #include #include @@ -57,6 +58,7 @@ class FeatureSet; namespace internal { class FieldSkipper; // wire_format_lite.h class WireFormat; +void InitializeLazyExtensionSet(); } // namespace internal } // namespace protobuf } // namespace google @@ -508,6 +510,8 @@ class PROTOBUF_EXPORT ExtensionSet { friend class google::protobuf::Reflection; friend class google::protobuf::internal::WireFormat; + friend void internal::InitializeLazyExtensionSet(); + const int32_t& GetRefInt32(int number, const int32_t& default_value) const; const int64_t& GetRefInt64(int number, const int64_t& default_value) const; const uint32_t& GetRefUInt32(int number, const uint32_t& default_value) const; @@ -579,7 +583,13 @@ class PROTOBUF_EXPORT ExtensionSet { virtual void UnusedKeyMethod(); // Dummy key method to avoid weak vtable. }; // Give access to function defined below to see LazyMessageExtension. - friend LazyMessageExtension* MaybeCreateLazyExtension(Arena* arena); + static LazyMessageExtension* MaybeCreateLazyExtensionImpl(Arena* arena); + static LazyMessageExtension* MaybeCreateLazyExtension(Arena* arena) { + auto* f = maybe_create_lazy_extension_.load(std::memory_order_relaxed); + return f != nullptr ? f(arena) : nullptr; + } + static std::atomic + maybe_create_lazy_extension_; struct Extension { // The order of these fields packs Extension into 24 bytes when using 8 // byte alignment. Consider this when adding or removing fields here. @@ -1529,10 +1539,6 @@ class ExtensionIdentifier { // Generated accessors -// Used to retrieve a lazy extension, may return nullptr in some environments. -extern PROTOBUF_ATTRIBUTE_WEAK ExtensionSet::LazyMessageExtension* -MaybeCreateLazyExtension(Arena* arena); - // Define a specialization of ExtensionIdentifier for bootstrapped extensions // that we need to register lazily. template <> diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index a897d8a2ab..2c6c5badc2 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -48,28 +48,30 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldMask, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldMask, _impl_.paths_), +const ::uint32_t + TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldMask, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::FieldMask, _impl_.paths_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, -1, -1, sizeof(::google::protobuf::FieldMask)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_FieldMask_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n google/protobuf/field_mask.proto\022\017goog" "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB" "\205\001\n\023com.google.protobufB\016FieldMaskProtoP" @@ -163,6 +165,16 @@ inline void FieldMask::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FieldMask::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FieldMask::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FieldMask::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -255,13 +267,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 39, 2> FieldMask::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FieldMask::_class_data_ = { - FieldMask::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FieldMask::GetClassData() const { - return &_class_data_; -} void FieldMask::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h index 89c042c67b..2c9f72726f 100644 --- a/src/google/protobuf/field_mask.pb.h +++ b/src/google/protobuf/field_mask.pb.h @@ -168,7 +168,7 @@ class PROTOBUF_EXPORT FieldMask final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -191,11 +191,9 @@ class PROTOBUF_EXPORT FieldMask final : protected: explicit FieldMask(::google::protobuf::Arena* arena); FieldMask(::google::protobuf::Arena* arena, const FieldMask& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/generated_message_bases.cc b/src/google/protobuf/generated_message_bases.cc index 319a0ae681..5821ac6157 100644 --- a/src/google/protobuf/generated_message_bases.cc +++ b/src/google/protobuf/generated_message_bases.cc @@ -7,6 +7,7 @@ #include "google/protobuf/generated_message_bases.h" +#include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl.h" #include "google/protobuf/parse_context.h" @@ -95,7 +96,11 @@ void ZeroFieldsBase::InternalSwap(ZeroFieldsBase* other) { } const Message::ClassData* ZeroFieldsBase::GetClassData() const { - static constexpr ClassData data = {&MergeImpl}; + static constexpr ClassData data = { + &MergeImpl, + nullptr, + &kDescriptorMethods, + }; return &data; } diff --git a/src/google/protobuf/generated_message_bases.h b/src/google/protobuf/generated_message_bases.h index 7a3943f62b..0f5e398a53 100644 --- a/src/google/protobuf/generated_message_bases.h +++ b/src/google/protobuf/generated_message_bases.h @@ -29,7 +29,7 @@ namespace internal { // rather than Message. class PROTOBUF_EXPORT ZeroFieldsBase : public Message { public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final { return true; } size_t ByteSizeLong() const final; int GetCachedSize() const { return _cached_size_.Get(); } diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 452fd5240d..a2e9c7cb83 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include "absl/base/call_once.h" #include "absl/base/casts.h" @@ -93,6 +94,9 @@ void InitializeFileDescriptorDefaultInstances() { #endif // !defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) } +void InitializeLazyExtensionSet() { +} + bool ParseNamedEnum(const EnumDescriptor* descriptor, absl::string_view name, int* value) { const EnumValueDescriptor* d = descriptor->FindValueByName(name); @@ -3412,6 +3416,7 @@ const internal::TcParseTableBase* Reflection::CreateTcParseTable() const { { /* is_lite */ false, /* uses_codegen */ false, + /* should_profile_driven_cluster_aux_table */ false, }, ReflectionOptionProvider(*this), has_bit_indices, inlined_string_indices); @@ -3660,6 +3665,7 @@ void AddDescriptorsImpl(const DescriptorTable* table) { // Reflection refers to the default fields so make sure they are initialized. internal::InitProtobufDefaults(); internal::InitializeFileDescriptorDefaultInstances(); + internal::InitializeLazyExtensionSet(); // Ensure all dependent descriptors are registered to the generated descriptor // pool and message factory. diff --git a/src/google/protobuf/generated_message_tctable_gen.cc b/src/google/protobuf/generated_message_tctable_gen.cc index 7c1736d63e..6740e35b50 100644 --- a/src/google/protobuf/generated_message_tctable_gen.cc +++ b/src/google/protobuf/generated_message_tctable_gen.cc @@ -8,6 +8,7 @@ #include "google/protobuf/generated_message_tctable_gen.h" #include +#include #include #include #include @@ -756,6 +757,35 @@ TailCallTableInfo::TailCallTableInfo( } } + auto is_non_cold = [](PerFieldOptions options) { + return options.presence_probability >= 0.005; + }; + size_t num_non_cold_subtables = 0; + if (message_options.should_profile_driven_cluster_aux_subtable) { + // We found that clustering non-cold subtables to the top of aux_entries + // achieves the best load tests results than other strategies (e.g., + // clustering all non-cold entries). + auto is_non_cold_subtable = [&](const FieldDescriptor* field) { + auto options = option_provider.GetForField(field); + // In the following code where we assign kSubTable to aux entries, only + // the following typed fields are supported. + return (field->type() == FieldDescriptor::TYPE_MESSAGE || + field->type() == FieldDescriptor::TYPE_GROUP) && + !field->is_map() && !HasLazyRep(field, options) && + !options.is_implicitly_weak && options.use_direct_tcparser_table && + is_non_cold(options); + }; + for (const FieldDescriptor* field : ordered_fields) { + if (is_non_cold_subtable(field)) { + num_non_cold_subtables++; + } + } + } + + size_t subtable_aux_idx_begin = aux_entries.size(); + size_t subtable_aux_idx = aux_entries.size(); + aux_entries.resize(aux_entries.size() + num_non_cold_subtables); + // Fill in mini table entries. for (const FieldDescriptor* field : ordered_fields) { auto options = option_provider.GetForField(field); @@ -797,12 +827,18 @@ TailCallTableInfo::TailCallTableInfo( TcParseTableBase::FieldEntry::kNoAuxIdx; } } else { - field_entries.back().aux_idx = aux_entries.size(); - aux_entries.push_back({options.is_implicitly_weak ? kSubMessageWeak - : options.use_direct_tcparser_table - ? kSubTable - : kSubMessage, - {field}}); + AuxType type = options.is_implicitly_weak ? kSubMessageWeak + : options.use_direct_tcparser_table ? kSubTable + : kSubMessage; + if (message_options.should_profile_driven_cluster_aux_subtable && + type == kSubTable && is_non_cold(options)) { + aux_entries[subtable_aux_idx] = {type, {field}}; + field_entries.back().aux_idx = subtable_aux_idx; + ++subtable_aux_idx; + } else { + field_entries.back().aux_idx = aux_entries.size(); + aux_entries.push_back({type, {field}}); + } } } else if (field->type() == FieldDescriptor::TYPE_ENUM && !cpp::HasPreservingUnknownEnumSemantics(field)) { @@ -845,6 +881,8 @@ TailCallTableInfo::TailCallTableInfo( entry.inlined_string_idx = idx; } } + ABSL_CHECK_EQ(subtable_aux_idx - subtable_aux_idx_begin, + num_non_cold_subtables); table_size_log2 = 0; // fallback value int num_fast_fields = -1; diff --git a/src/google/protobuf/generated_message_tctable_gen.h b/src/google/protobuf/generated_message_tctable_gen.h index bf202712a4..514f590a57 100644 --- a/src/google/protobuf/generated_message_tctable_gen.h +++ b/src/google/protobuf/generated_message_tctable_gen.h @@ -38,6 +38,8 @@ struct PROTOBUF_EXPORT TailCallTableInfo { struct MessageOptions { bool is_lite; bool uses_codegen; + // TODO: remove this after A/B test is done. + bool should_profile_driven_cluster_aux_subtable; }; struct PerFieldOptions { // For presence awareness (e.g. PDProto). diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc index 531d0556a7..bf5a97b7a5 100644 --- a/src/google/protobuf/generated_message_tctable_lite.cc +++ b/src/google/protobuf/generated_message_tctable_lite.cc @@ -166,7 +166,7 @@ const TcParseTableBase::FieldEntry* TcParser::FindFieldEntry( } const uint16_t* lookup_table = table->field_lookup_begin(); for (;;) { -#ifdef PROTOBUF_LITTLE_ENDIAN +#ifdef ABSL_IS_LITTLE_ENDIAN memcpy(&fstart, lookup_table, sizeof(fstart)); #else fstart = lookup_table[0] | (lookup_table[1] << 16); diff --git a/src/google/protobuf/implicit_weak_message.h b/src/google/protobuf/implicit_weak_message.h index 170155a2c9..0428d9eb32 100644 --- a/src/google/protobuf/implicit_weak_message.h +++ b/src/google/protobuf/implicit_weak_message.h @@ -56,7 +56,14 @@ class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite { static const ImplicitWeakMessage* default_instance(); - std::string GetTypeName() const override { return ""; } + const ClassData* GetClassData() const final { + struct Data { + ClassData header; + char name[1]; + }; + static constexpr Data data = {{}, ""}; + return &data.header; + } MessageLite* New(Arena* arena) const override { return Arena::CreateMessage(arena); diff --git a/src/google/protobuf/io/BUILD.bazel b/src/google/protobuf/io/BUILD.bazel index 0578742d62..a5c44e2aad 100644 --- a/src/google/protobuf/io/BUILD.bazel +++ b/src/google/protobuf/io/BUILD.bazel @@ -23,7 +23,7 @@ cc_library( "zero_copy_stream_impl_lite.h", ], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":io_win32", "//src/google/protobuf:arena", @@ -39,7 +39,7 @@ cc_library( testonly = 1, hdrs = ["test_zero_copy_stream.h"], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":io", "//src/google/protobuf/stubs", @@ -90,7 +90,7 @@ cc_library( srcs = ["printer.cc"], hdrs = ["printer.h"], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":zero_copy_sink", "//src/google/protobuf/stubs", @@ -119,7 +119,7 @@ cc_library( "tokenizer.h", ], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":io", "//src/google/protobuf/stubs", @@ -134,7 +134,7 @@ cc_library( srcs = ["gzip_stream.cc"], hdrs = ["gzip_stream.h"], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":io", "//src/google/protobuf/stubs", @@ -151,7 +151,7 @@ cc_library( srcs = ["io_win32.cc"], hdrs = ["io_win32.h"], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index fdfc2d096e..61f6393087 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -893,7 +893,7 @@ uint8_t* EpsCopyOutputStream::WriteAliasedRaw(const void* data, int size, } } -#ifndef PROTOBUF_LITTLE_ENDIAN +#ifndef ABSL_IS_LITTLE_ENDIAN uint8_t* EpsCopyOutputStream::WriteRawLittleEndian32(const void* data, int size, uint8_t* ptr) { auto p = static_cast(data); diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 09c66aff38..ecb0f2ec57 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -912,7 +912,7 @@ class PROTOBUF_EXPORT EpsCopyOutputStream { template uint8_t* WriteRawLittleEndian(const void* data, int size, uint8_t* ptr); -#if !defined(PROTOBUF_LITTLE_ENDIAN) || \ +#if !defined(ABSL_IS_LITTLE_ENDIAN) || \ defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) uint8_t* WriteRawLittleEndian32(const void* data, int size, uint8_t* ptr); uint8_t* WriteRawLittleEndian64(const void* data, int size, uint8_t* ptr); @@ -960,7 +960,7 @@ template <> inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<4>(const void* data, int size, uint8_t* ptr) { -#if defined(PROTOBUF_LITTLE_ENDIAN) && \ +#if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) return WriteRaw(data, size, ptr); #else @@ -971,7 +971,7 @@ template <> inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<8>(const void* data, int size, uint8_t* ptr) { -#if defined(PROTOBUF_LITTLE_ENDIAN) && \ +#if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) return WriteRaw(data, size, ptr); #else @@ -1320,7 +1320,7 @@ inline bool CodedInputStream::ReadVarintSizeAsInt(int* value) { // static inline const uint8_t* CodedInputStream::ReadLittleEndian32FromArray( const uint8_t* buffer, uint32_t* value) { -#if defined(PROTOBUF_LITTLE_ENDIAN) && \ +#if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) memcpy(value, buffer, sizeof(*value)); return buffer + sizeof(*value); @@ -1335,7 +1335,7 @@ inline const uint8_t* CodedInputStream::ReadLittleEndian32FromArray( // static inline const uint8_t* CodedInputStream::ReadLittleEndian64FromArray( const uint8_t* buffer, uint64_t* value) { -#if defined(PROTOBUF_LITTLE_ENDIAN) && \ +#if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) memcpy(value, buffer, sizeof(*value)); return buffer + sizeof(*value); @@ -1354,7 +1354,7 @@ inline const uint8_t* CodedInputStream::ReadLittleEndian64FromArray( } inline bool CodedInputStream::ReadLittleEndian32(uint32_t* value) { -#if defined(PROTOBUF_LITTLE_ENDIAN) && \ +#if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { buffer_ = ReadLittleEndian32FromArray(buffer_, value); @@ -1368,7 +1368,7 @@ inline bool CodedInputStream::ReadLittleEndian32(uint32_t* value) { } inline bool CodedInputStream::ReadLittleEndian64(uint64_t* value) { -#if defined(PROTOBUF_LITTLE_ENDIAN) && \ +#if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { buffer_ = ReadLittleEndian64FromArray(buffer_, value); @@ -1646,7 +1646,7 @@ inline uint8_t* CodedOutputStream::WriteVarint32SignExtendedToArray( inline uint8_t* CodedOutputStream::WriteLittleEndian32ToArray(uint32_t value, uint8_t* target) { -#if defined(PROTOBUF_LITTLE_ENDIAN) && \ +#if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) memcpy(target, &value, sizeof(value)); #else @@ -1660,7 +1660,7 @@ inline uint8_t* CodedOutputStream::WriteLittleEndian32ToArray(uint32_t value, inline uint8_t* CodedOutputStream::WriteLittleEndian64ToArray(uint64_t value, uint8_t* target) { -#if defined(PROTOBUF_LITTLE_ENDIAN) && \ +#if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) memcpy(target, &value, sizeof(value)); #else 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 3dd4b7337e..752dff20fd 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -617,7 +617,7 @@ bool CordOutputStream::Next(void** data, int* size) { case State::kFull: assert(buffer_.length() > 0); cord_.Append(std::move(buffer_)); - PROTOBUF_FALLTHROUGH_INTENDED; + ABSL_FALLTHROUGH_INTENDED; case State::kEmpty: assert(buffer_.length() == 0); buffer_ = absl::CordBuffer::CreateWithDefaultLimit(desired_size); diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 8aa9e45fe3..8388f8a2e5 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -678,7 +678,7 @@ class MapField final : public TypeDefinedMapFieldBase { template -constexpr MapFieldBase::VTable +PROTOBUF_CONSTINIT const MapFieldBase::VTable MapField::kVTable = MapField::template MakeVTable(); diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index b4b1a40c51..2cf07dbdf4 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -58,6 +58,10 @@ using internal::ReflectionOps; using internal::WireFormat; using internal::WireFormatLite; +void Message::MergeImpl(Message& to, const Message& from) { + ReflectionOps::Merge(from, &to); +} + void Message::MergeFrom(const Message& from) { auto* class_to = GetClassData(); auto* class_from = from.GetClassData(); @@ -70,6 +74,15 @@ void Message::MergeFrom(const Message& from) { merge_to_from(*this, from); } +const MessageLite::ClassData* Message::GetClassData() const { + static constexpr ClassData data = { + &MergeImpl, + nullptr, + &kDescriptorMethods, + }; + return &data; +} + void Message::CheckTypeAndMergeFrom(const MessageLite& other) { MergeFrom(*DownCast(&other)); } @@ -99,10 +112,6 @@ void Message::CopyFrom(const Message& from) { } } -std::string Message::GetTypeName() const { - return GetDescriptor()->full_name(); -} - void Message::Clear() { ReflectionOps::Clear(this); } bool Message::IsInitialized() const { @@ -179,9 +188,28 @@ size_t Message::MaybeComputeUnknownFieldsSize( } size_t Message::SpaceUsedLong() const { - return GetReflection()->SpaceUsedLong(*this); + auto* reflection = GetReflection(); + if (PROTOBUF_PREDICT_TRUE(reflection != nullptr)) { + return reflection->SpaceUsedLong(*this); + } + // The only case that does not have reflection is RawMessage. + return internal::DownCast(*this) + .SpaceUsedLong(); +} + +static std::string GetTypeNameImpl(const MessageLite& msg) { + return DownCast(msg).GetDescriptor()->full_name(); } +static std::string InitializationErrorStringImpl(const MessageLite& msg) { + return DownCast(msg).InitializationErrorString(); +} + +constexpr MessageLite::DescriptorMethods Message::kDescriptorMethods = { + GetTypeNameImpl, + InitializationErrorStringImpl, +}; + namespace internal { void* CreateSplitMessageGeneric(Arena* arena, const void* default_split, size_t size, const void* message, diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 1fb5368a23..6ddbaec21c 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -257,7 +257,7 @@ class PROTOBUF_EXPORT Message : public MessageLite { // messages which will be merged. Repeated fields will be concatenated. // The given message must be of the same type as this message (i.e. the // exact same class). - virtual void MergeFrom(const Message& from); + void MergeFrom(const Message& from); // Verifies that IsInitialized() returns true. ABSL_CHECK-fails otherwise, // with a nice error message. @@ -271,7 +271,7 @@ class PROTOBUF_EXPORT Message : public MessageLite { // Like FindInitializationErrors, but joins all the strings, delimited by // commas, and returns them. - std::string InitializationErrorString() const override; + std::string InitializationErrorString() const; // Clears all unknown fields from this message and all embedded messages. // Normally, if unknown tag numbers are encountered when parsing a message, @@ -286,8 +286,7 @@ class PROTOBUF_EXPORT Message : public MessageLite { void DiscardUnknownFields(); // Computes (an estimate of) the total number of bytes currently used for - // storing the message in memory. The default implementation calls the - // Reflection object's SpaceUsed() method. + // storing the message in memory. // // SpaceUsed() is noticeably slower than ByteSize(), as it is implemented // using reflection (rather than the generated code implementation for @@ -297,7 +296,7 @@ class PROTOBUF_EXPORT Message : public MessageLite { // 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; + size_t SpaceUsedLong() const; [[deprecated("Please use SpaceUsedLong() instead")]] int SpaceUsed() const { return internal::ToIntSize(SpaceUsedLong()); @@ -330,7 +329,6 @@ class PROTOBUF_EXPORT Message : public MessageLite { // These methods are pure-virtual in MessageLite, but Message provides // reflection-based default implementations. - std::string GetTypeName() const override; void Clear() override; // Returns whether all required fields have been set. Note that required @@ -370,6 +368,15 @@ class PROTOBUF_EXPORT Message : public MessageLite { size_t MaybeComputeUnknownFieldsSize(size_t total_size, internal::CachedSize* cached_size) const; + // Reflection based version for reflection based types. + static void MergeImpl(Message& to, const Message& from); + + static const DescriptorMethods kDescriptorMethods; + + // Default implementation using reflection. Avoids bloat in MapEntry. + // Generated types will make their own. + const ClassData* GetClassData() const override; + }; namespace internal { @@ -1565,6 +1572,12 @@ bool SplitFieldHasExtraIndirectionStatic(const FieldDescriptor* field) { return ret; } +class RawMessageBase : public Message { + public: + using Message::Message; + virtual size_t SpaceUsedLong() const = 0; +}; + } // namespace internal template diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 4505222763..12ee82f4ca 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -44,19 +44,38 @@ namespace google { namespace protobuf { +std::string MessageLite::GetTypeName() const { + auto* data = GetClassData(); + ABSL_DCHECK(data != nullptr); + + if (data->descriptor_methods != nullptr) { + // For !LITE messages, we use the descriptor method function. + return data->descriptor_methods->get_type_name(*this); + } + + // For LITE messages, the type name is a char[] just beyond ClassData. + return reinterpret_cast(data) + sizeof(ClassData); +} + void MessageLite::OnDemandRegisterArenaDtor(Arena* arena) { if (arena == nullptr) return; auto* data = GetClassData(); - if (data != nullptr && data->on_demand_register_arena_dtor != nullptr) { + ABSL_DCHECK(data != nullptr); + + if (data->on_demand_register_arena_dtor != nullptr) { data->on_demand_register_arena_dtor(*this, *arena); } } -const MessageLite::ClassData* MessageLite::GetClassData() const { - return nullptr; -} - std::string MessageLite::InitializationErrorString() const { + auto* data = GetClassData(); + ABSL_DCHECK(data != nullptr); + + if (data->descriptor_methods != nullptr) { + // For !LITE messages, we use the descriptor method function. + return data->descriptor_methods->initialization_error_string(*this); + } + return "(cannot determine missing fields for lite message)"; } diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index de8bd19aa0..cbece7c799 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -211,7 +211,7 @@ class PROTOBUF_EXPORT MessageLite { // Basic Operations ------------------------------------------------ // Get the name of this message type, e.g. "foo.bar.BazProto". - virtual std::string GetTypeName() const = 0; + std::string GetTypeName() const; // Construct a new instance of the same type. Ownership is passed to the // caller. @@ -221,6 +221,11 @@ class PROTOBUF_EXPORT MessageLite { // if arena is a nullptr. virtual MessageLite* New(Arena* arena) const = 0; + // Returns the arena, if any, that directly owns this message and its internal + // memory (Arena::Own is different in that the arena doesn't directly own the + // internal memory). This method is used in proto's implementation for + // swapping, moving and setting allocated, for deciding whether the ownership + // of this message or its internal memory could be changed. Arena* GetArena() const { return _internal_metadata_.arena(); } // Clear all fields of the message and set them to their default values. @@ -235,7 +240,7 @@ class PROTOBUF_EXPORT MessageLite { // This is not implemented for Lite messages -- it just returns "(cannot // determine missing fields for lite message)". However, it is implemented // for full messages. See message.h. - virtual std::string InitializationErrorString() const; + std::string InitializationErrorString() const; // If |other| is the exact same class as this, calls MergeFrom(). Otherwise, // results are undefined (probably crash). @@ -273,34 +278,34 @@ class PROTOBUF_EXPORT MessageLite { // format. A successful return does not indicate the entire input is // consumed, ensure you call ConsumedEntireMessage() to check that if // applicable. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromCodedStream( + ABSL_ATTRIBUTE_REINITIALIZES bool ParseFromCodedStream( io::CodedInputStream* input); // Like ParseFromCodedStream(), but accepts messages that are missing // required fields. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCodedStream( + ABSL_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCodedStream( io::CodedInputStream* input); // Read a protocol buffer from the given zero-copy input stream. If // successful, the entire input will be consumed. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromZeroCopyStream( + ABSL_ATTRIBUTE_REINITIALIZES bool ParseFromZeroCopyStream( io::ZeroCopyInputStream* input); // Like ParseFromZeroCopyStream(), but accepts messages that are missing // required fields. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromZeroCopyStream( + ABSL_ATTRIBUTE_REINITIALIZES bool ParsePartialFromZeroCopyStream( io::ZeroCopyInputStream* input); // Parse a protocol buffer from a file descriptor. If successful, the entire // input will be consumed. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromFileDescriptor( + ABSL_ATTRIBUTE_REINITIALIZES bool ParseFromFileDescriptor( int file_descriptor); // Like ParseFromFileDescriptor(), but accepts messages that are missing // required fields. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromFileDescriptor( + ABSL_ATTRIBUTE_REINITIALIZES bool ParsePartialFromFileDescriptor( int file_descriptor); // Parse a protocol buffer from a C++ istream. If successful, the entire // input will be consumed. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromIstream(std::istream* input); + ABSL_ATTRIBUTE_REINITIALIZES bool ParseFromIstream(std::istream* input); // Like ParseFromIstream(), but accepts messages that are missing // required fields. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromIstream( + ABSL_ATTRIBUTE_REINITIALIZES bool ParsePartialFromIstream( std::istream* input); // Read a protocol buffer from the given zero-copy input stream, expecting // the message to be exactly "size" bytes long. If successful, exactly @@ -310,29 +315,28 @@ class PROTOBUF_EXPORT MessageLite { // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are // missing required fields. bool MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromBoundedZeroCopyStream( + ABSL_ATTRIBUTE_REINITIALIZES bool ParseFromBoundedZeroCopyStream( io::ZeroCopyInputStream* input, int size); // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are // missing required fields. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromBoundedZeroCopyStream( + ABSL_ATTRIBUTE_REINITIALIZES bool ParsePartialFromBoundedZeroCopyStream( io::ZeroCopyInputStream* input, int size); // Parses a protocol buffer contained in a string. Returns true on success. // This function takes a string in the (non-human-readable) binary wire // format, matching the encoding output by MessageLite::SerializeToString(). // If you'd like to convert a human-readable string into a protocol buffer // object, see google::protobuf::TextFormat::ParseFromString(). - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(absl::string_view data); + ABSL_ATTRIBUTE_REINITIALIZES bool ParseFromString(absl::string_view data); // Like ParseFromString(), but accepts messages that are missing // required fields. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString( + ABSL_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString( absl::string_view data); // Parse a protocol buffer contained in an array of bytes. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data, - int size); + ABSL_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data, int size); // Like ParseFromArray(), but accepts messages that are missing // required fields. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromArray(const void* data, - int size); + ABSL_ATTRIBUTE_REINITIALIZES bool ParsePartialFromArray(const void* data, + int size); // Reads a protocol buffer from the stream and merges it into this @@ -418,10 +422,10 @@ class PROTOBUF_EXPORT MessageLite { // required fields. bool MergePartialFromCord(const absl::Cord& cord); // Parse a protocol buffer contained in a Cord. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromCord(const absl::Cord& cord); + ABSL_ATTRIBUTE_REINITIALIZES bool ParseFromCord(const absl::Cord& cord); // Like ParseFromCord(), but accepts messages that are missing // required fields. - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCord( + ABSL_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCord( const absl::Cord& cord); // Serialize the message and store it in the given Cord. All required @@ -505,28 +509,29 @@ class PROTOBUF_EXPORT MessageLite { return Arena::CreateMaybeMessage(arena); } -#ifdef PROTOBUF_EXPLICIT_CONSTRUCTORS template static T* CreateMaybeMessage(Arena* arena, const T& from) { return Arena::CreateMaybeMessage(arena, from); } -#endif // PROTOBUF_EXPLICIT_CONSTRUCTORS inline explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {} - // Returns the arena, if any, that directly owns this message and its internal - // memory (Arena::Own is different in that the arena doesn't directly own the - // internal memory). This method is used in proto's implementation for - // swapping, moving and setting allocated, for deciding whether the ownership - // of this message or its internal memory could be changed. - Arena* GetOwningArena() const { return _internal_metadata_.arena(); } - + // We use a secondary vtable for descriptor based methods. This way ClassData + // does not growth with the number of descriptor methods. This avoids extra + // costs in MessageLite. + struct DescriptorMethods { + std::string (*get_type_name)(const MessageLite&); + std::string (*initialization_error_string)(const MessageLite&); + }; struct ClassData { // Note: The order of arguments in the functions is chosen so that it has // the same ABI as the member function that calls them. Eg the `this` // pointer becomes the first argument in the free function. void (*merge_to_from)(Message& to, const Message& from_msg); void (*on_demand_register_arena_dtor)(MessageLite& msg, Arena& arena); + // LITE objects (ie !descriptor_methods) collocate their name as a + // char[] just beyond the ClassData. + const DescriptorMethods* descriptor_methods; }; // GetClassData() returns a pointer to a ClassData struct which @@ -534,9 +539,9 @@ class PROTOBUF_EXPORT MessageLite { // property is used in order to quickly determine whether two messages are // of the same type. // - // This is a work in progress. Currently only SPEED messages return an - // instance. In the future all message types will return one. - virtual const ClassData* GetClassData() const; + // This is a work in progress. There are still some types (eg MapEntry) that + // return a default table instead of a unique one. + virtual const ClassData* GetClassData() const = 0; internal::InternalMetadata _internal_metadata_; diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc index 4e07c69367..0dae9657fa 100644 --- a/src/google/protobuf/message_unittest.inc +++ b/src/google/protobuf/message_unittest.inc @@ -1937,9 +1937,10 @@ TEST(MESSAGE_TEST_NAME, TestRegressionInlinedStringAuxIdxMismatchOnFastParser) { if (table != nullptr && table->fast_entry(1)->target() == internal::TcParser::FastSiS1) { // optional string str1 = 1; + // The aux_idx points to the inlined_string_idx and not the actual aux_idx. EXPECT_EQ(table->fast_entry(1)->bits.aux_idx(), 1); // optional InlinedStringIdxRegressionProto sub = 2; - EXPECT_EQ(table->fast_entry(2)->bits.aux_idx(), 2); + EXPECT_EQ(table->fast_entry(2)->bits.aux_idx(), 1); // optional string str2 = 3; // The aux_idx points to the inlined_string_idx and not the actual aux_idx. EXPECT_EQ(table->fast_entry(3)->bits.aux_idx(), 2); diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h index df12ee1ab5..776773c5cb 100644 --- a/src/google/protobuf/parse_context.h +++ b/src/google/protobuf/parse_context.h @@ -883,7 +883,7 @@ static const char* VarintParseSlowArm(const char* p, uint64_t* out, template PROTOBUF_NODISCARD const char* VarintParse(const char* p, T* out) { -#if defined(__aarch64__) && defined(PROTOBUF_LITTLE_ENDIAN) +#if defined(__aarch64__) && defined(ABSL_IS_LITTLE_ENDIAN) // This optimization is not supported in big endian mode uint64_t first8; std::memcpy(&first8, p, sizeof(first8)); @@ -1178,7 +1178,7 @@ const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size, out->Reserve(old_entries + num); int block_size = num * sizeof(T); auto dst = out->AddNAlreadyReserved(num); -#ifdef PROTOBUF_LITTLE_ENDIAN +#ifdef ABSL_IS_LITTLE_ENDIAN std::memcpy(dst, ptr, block_size); #else for (int i = 0; i < num; i++) @@ -1197,7 +1197,7 @@ const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size, int old_entries = out->size(); out->Reserve(old_entries + num); auto dst = out->AddNAlreadyReserved(num); -#ifdef PROTOBUF_LITTLE_ENDIAN +#ifdef ABSL_IS_LITTLE_ENDIAN ABSL_CHECK(dst != nullptr) << out << "," << num; std::memcpy(dst, ptr, block_size); #else diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index 4b1d2b46cd..21f21bd57a 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc @@ -311,64 +311,6 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #define PROTOBUF_TAILCALL false #endif -#ifdef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED -#error PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED was previously defined -#endif -#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required) -#define PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED(...) \ - __attribute__((exclusive_locks_required(__VA_ARGS__))) -#else -#define PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED(...) -#endif - -#ifdef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS -#error PROTOBUF_NO_THREAD_SAFETY_ANALYSIS was previously defined -#endif -#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis) -#define PROTOBUF_NO_THREAD_SAFETY_ANALYSIS \ - __attribute__((no_thread_safety_analysis)) -#else -#define PROTOBUF_NO_THREAD_SAFETY_ANALYSIS -#endif - -#ifdef PROTOBUF_GUARDED_BY -#error PROTOBUF_GUARDED_BY was previously defined -#endif -#if ABSL_HAVE_ATTRIBUTE(guarded_by) -#define PROTOBUF_GUARDED_BY(x) __attribute__((guarded_by(x))) -#else -#define PROTOBUF_GUARDED_BY(x) -#endif - -#ifdef PROTOBUF_LOCKS_EXCLUDED -#error PROTOBUF_LOCKS_EXCLUDED was previously defined -#endif -#if ABSL_HAVE_ATTRIBUTE(locks_excluded) -#define PROTOBUF_LOCKS_EXCLUDED(...) \ - __attribute__((locks_excluded(__VA_ARGS__))) -#else -#define PROTOBUF_LOCKS_EXCLUDED(...) -#endif - -#ifdef PROTOBUF_COLD -#error PROTOBUF_COLD was previously defined -#endif -#if ABSL_HAVE_ATTRIBUTE(cold) || defined(__GNUC__) -# define PROTOBUF_COLD __attribute__((cold)) -#else -# define PROTOBUF_COLD -#endif - -#ifdef PROTOBUF_SECTION_VARIABLE -#error PROTOBUF_SECTION_VARIABLE was previously defined -#endif -#if (ABSL_HAVE_ATTRIBUTE(section) || defined(__GNUC__)) && defined(__ELF__) -// Place a variable in the given ELF section. -# define PROTOBUF_SECTION_VARIABLE(x) __attribute__((section(#x))) -#else -# define PROTOBUF_SECTION_VARIABLE(x) -#endif - #if defined(__clang__) #define PROTOBUF_IGNORE_DEPRECATION_START \ _Pragma("clang diagnostic push") \ @@ -386,24 +328,6 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #define PROTOBUF_IGNORE_DEPRECATION_STOP #endif -#ifdef PROTOBUF_RETURNS_NONNULL -#error PROTOBUF_RETURNS_NONNULL was previously defined -#endif -#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) || defined(__GNUC__) -#define PROTOBUF_RETURNS_NONNULL __attribute__((returns_nonnull)) -#else -#define PROTOBUF_RETURNS_NONNULL -#endif - -#ifdef PROTOBUF_ATTRIBUTE_REINITIALIZES -#error PROTOBUF_ATTRIBUTE_REINITIALIZES was previously defined -#endif -#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) -#define PROTOBUF_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] -#else -#define PROTOBUF_ATTRIBUTE_REINITIALIZES -#endif - // The minimum library version which works with the current version of the // headers. #define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 4025000 @@ -572,32 +496,10 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #error PROTOBUF_FORCE_COPY_DEFAULT_STRING was previously defined #endif -// Set (and leave set) PROTOBUF_EXPLICIT_CONSTRUCTORS -// This flag changes the internal implementation class and its uses from using -// aggregate initialization to using explicit constructor based initialization. -// TODO: remove this flag and make the code permanent. -#ifndef PROTOBUF_EXPLICIT_CONSTRUCTORS -#define PROTOBUF_EXPLICIT_CONSTRUCTORS -#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 -#if ABSL_HAVE_CPP_ATTRIBUTE(fallthrough) -#define PROTOBUF_FALLTHROUGH_INTENDED [[fallthrough]] -#elif ABSL_HAVE_FEATURE(cxx_attributes) && \ - __has_warning("-Wimplicit-fallthrough") -#define PROTOBUF_FALLTHROUGH_INTENDED [[clang::fallthrough]] -#elif defined(__GNUC__) -#define PROTOBUF_FALLTHROUGH_INTENDED [[gnu::fallthrough]] -#else -#define PROTOBUF_FALLTHROUGH_INTENDED -#endif - // Specify memory alignment for structs, classes, etc. // Use like: // class PROTOBUF_ALIGNAS(16) MyClass { ... } @@ -645,22 +547,6 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #define PROTOBUF_THREAD_LOCAL __thread #endif -// TODO: cleanup PROTOBUF_LITTLE_ENDIAN in various 3p forks. -#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define PROTOBUF_LITTLE_ENDIAN 1 -#ifdef PROTOBUF_BIG_ENDIAN -#error Conflicting PROTOBUF_BIG_ENDIAN was previously defined -#endif -#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define PROTOBUF_BIG_ENDIAN 1 -#elif defined(_WIN32) || defined(__x86_64__) || defined(__aarch64__) -#define PROTOBUF_LITTLE_ENDIAN 1 -#else -#error "endian detection failed for current compiler" -#endif - #ifdef PROTOBUF_CONSTINIT #error PROTOBUF_CONSTINIT was previously defined #endif diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc index 43cdc0088f..49aeb64865 100644 --- a/src/google/protobuf/port_undef.inc +++ b/src/google/protobuf/port_undef.inc @@ -31,13 +31,9 @@ #undef PROTOBUF_NDEBUG_INLINE #undef PROTOBUF_MUSTTAIL #undef PROTOBUF_TAILCALL -#undef PROTOBUF_COLD #undef PROTOBUF_NOINLINE -#undef PROTOBUF_SECTION_VARIABLE #undef PROTOBUF_IGNORE_DEPRECATION_START #undef PROTOBUF_IGNORE_DEPRECATION_STOP -#undef PROTOBUF_RETURNS_NONNULL -#undef PROTOBUF_ATTRIBUTE_REINITIALIZES #undef PROTOBUF_RTTI #undef PROTOBUF_VERSION #undef PROTOBUF_VERSION_SUFFIX @@ -48,7 +44,6 @@ #undef PROTOBUF_MIN_PROTOC_VERSION #undef PROTOBUF_PREDICT_TRUE #undef PROTOBUF_PREDICT_FALSE -#undef PROTOBUF_FALLTHROUGH_INTENDED #undef PROTOBUF_EXPORT #undef PROTOC_EXPORT #undef PROTOBUF_NODISCARD @@ -67,8 +62,6 @@ #undef PROTOBUF_ALIGNAS #undef PROTOBUF_FINAL #undef PROTOBUF_THREAD_LOCAL -#undef PROTOBUF_LITTLE_ENDIAN -#undef PROTOBUF_BIG_ENDIAN #undef PROTOBUF_CONSTINIT #undef PROTOBUF_CONSTEXPR #undef PROTOBUF_CONSTINIT_DEFAULT_INSTANCES @@ -88,10 +81,6 @@ #undef PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION #undef PROTOBUF_BUILTIN_CONSTANT_P #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 PROTO2_IS_OSS #undef PROTOBUF_NO_THREADLOCAL diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 7e3f8d2e36..0647790b78 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -204,13 +204,13 @@ class RepeatedField final // Calling this routine inside a loop can cause quadratic behavior. void ExtractSubrange(int start, int num, Element* elements); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear(); + ABSL_ATTRIBUTE_REINITIALIZES void Clear(); void MergeFrom(const RepeatedField& other); - PROTOBUF_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedField& other); + ABSL_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedField& other); // Replaces the contents with RepeatedField(begin, end). template - PROTOBUF_ATTRIBUTE_REINITIALIZES void Assign(Iter begin, Iter end); + ABSL_ATTRIBUTE_REINITIALIZES void Assign(Iter begin, Iter end); // Reserves space to expand the field to at least the given size. If the // array is grown, it will always be at least doubled in size. @@ -293,7 +293,10 @@ class RepeatedField final // Gets the Arena on which this RepeatedField stores its elements. // Note: this can be inaccurate for split default fields so we make this // function non-const. - inline Arena* GetArena() { return GetOwningArena(); } + inline Arena* GetArena() { + return (total_size_ == 0) ? static_cast(arena_or_elements_) + : rep()->arena; + } // For internal use only. // @@ -327,12 +330,6 @@ class RepeatedField final RepeatedField(Arena* arena, const RepeatedField& rhs); - // Gets the Arena on which this RepeatedField stores its elements. - inline Arena* GetOwningArena() const { - return (total_size_ == 0) ? static_cast(arena_or_elements_) - : 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 diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index f5529ed784..814f0c8d79 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -704,9 +704,9 @@ TEST(RepeatedField, CopyConstructIntegers) { EXPECT_EQ(2, fields1.Get(1)); RepeatedType fields2(token, nullptr, original); - ASSERT_EQ(2, fields1.size()); - EXPECT_EQ(1, fields1.Get(0)); - EXPECT_EQ(2, fields1.Get(1)); + ASSERT_EQ(2, fields2.size()); + EXPECT_EQ(1, fields2.Get(0)); + EXPECT_EQ(2, fields2.Get(1)); } TEST(RepeatedField, CopyConstructCords) { @@ -1677,6 +1677,14 @@ TEST(RepeatedPtrField, AddAllocated) { EXPECT_EQ(moo, &field.Get(index)); } +TEST(RepeatedPtrField, AddMethodsDontAcceptNull) { +#if !defined(NDEBUG) + RepeatedPtrField field; + EXPECT_DEATH(field.AddAllocated(nullptr), "nullptr"); + EXPECT_DEATH(field.UnsafeArenaAddAllocated(nullptr), "nullptr"); +#endif +} + TEST(RepeatedPtrField, AddAllocatedDifferentArena) { RepeatedPtrField field; Arena arena; diff --git a/src/google/protobuf/repeated_ptr_field.cc b/src/google/protobuf/repeated_ptr_field.cc index 19b4ca59c4..734a6a7188 100644 --- a/src/google/protobuf/repeated_ptr_field.cc +++ b/src/google/protobuf/repeated_ptr_field.cc @@ -20,6 +20,7 @@ #include "absl/log/absl_check.h" #include "google/protobuf/arena.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" @@ -34,10 +35,11 @@ namespace internal { void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { ABSL_DCHECK(extend_amount > 0); constexpr size_t ptr_size = sizeof(rep()->elements[0]); - int new_capacity = total_size_ + extend_amount; + int capacity = Capacity(); + int new_capacity = capacity + extend_amount; Arena* arena = GetArena(); new_capacity = internal::CalculateReserveSize( - total_size_, new_capacity); + capacity, new_capacity); ABSL_CHECK_LE( static_cast(new_capacity), static_cast( @@ -45,7 +47,6 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { << "Requested size is too large to fit into size_t."; size_t bytes = kRepHeaderSize + ptr_size * new_capacity; Rep* new_rep; - void* old_tagged_ptr = tagged_rep_or_elem_; if (arena == nullptr) { internal::SizedPtr res = internal::AllocateAtLeast(bytes); new_capacity = static_cast((res.n - kRepHeaderSize) / ptr_size); @@ -55,18 +56,17 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { } if (using_sso()) { - new_rep->allocated_size = old_tagged_ptr != nullptr ? 1 : 0; - new_rep->elements[0] = old_tagged_ptr; + new_rep->allocated_size = tagged_rep_or_elem_ != nullptr ? 1 : 0; + new_rep->elements[0] = tagged_rep_or_elem_; } else { - Rep* old_rep = - reinterpret_cast(reinterpret_cast(old_tagged_ptr) - 1); + Rep* old_rep = rep(); if (old_rep->allocated_size > 0) { memcpy(new_rep->elements, old_rep->elements, old_rep->allocated_size * ptr_size); } new_rep->allocated_size = old_rep->allocated_size; - size_t old_size = total_size_ * ptr_size + kRepHeaderSize; + size_t old_size = capacity * ptr_size + kRepHeaderSize; if (arena == nullptr) { internal::SizedDelete(old_rep, old_size); } else { @@ -76,13 +76,14 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { tagged_rep_or_elem_ = reinterpret_cast(reinterpret_cast(new_rep) + 1); - total_size_ = new_capacity; + capacity_proxy_ = new_capacity - kSSOCapacity; return &new_rep->elements[current_size_]; } void RepeatedPtrFieldBase::Reserve(int capacity) { - if (capacity > total_size_) { - InternalExtend(capacity - total_size_); + int delta = capacity - Capacity(); + if (delta > 0) { + InternalExtend(delta); } } @@ -98,7 +99,7 @@ void RepeatedPtrFieldBase::DestroyProtos() { for (int i = 0; i < n; i++) { delete static_cast(elements[i]); } - const size_t size = total_size_ * sizeof(elements[0]) + kRepHeaderSize; + const size_t size = Capacity() * sizeof(elements[0]) + kRepHeaderSize; internal::SizedDelete(r, size); } @@ -115,7 +116,9 @@ void* RepeatedPtrFieldBase::AddOutOfLineHelper(void* obj) { ExchangeCurrentSize(1); return tagged_rep_or_elem_ = obj; } - if (using_sso() || rep()->allocated_size == total_size_) { + // Not using `AllocatedSizeAtCapacity` because it's already known that + // `tagged_rep_or_elem_ != nullptr`. + if (using_sso() || rep()->allocated_size >= Capacity()) { InternalExtend(1); // Equivalent to "Reserve(total_size_ + 1)" } Rep* r = rep(); @@ -134,7 +137,7 @@ void* RepeatedPtrFieldBase::AddOutOfLineHelper(ElementFactory factory) { } else { absl::PrefetchToLocalCache(rep()); } - if (PROTOBUF_PREDICT_FALSE(current_size_ == total_size_)) { + if (PROTOBUF_PREDICT_FALSE(SizeAtCapacity())) { InternalExtend(1); } else { Rep* r = rep(); diff --git a/src/google/protobuf/repeated_ptr_field.h b/src/google/protobuf/repeated_ptr_field.h index d38232462e..fe38aac865 100644 --- a/src/google/protobuf/repeated_ptr_field.h +++ b/src/google/protobuf/repeated_ptr_field.h @@ -177,12 +177,12 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { constexpr RepeatedPtrFieldBase() : tagged_rep_or_elem_(nullptr), current_size_(0), - total_size_(kSSOCapacity), + capacity_proxy_(0), arena_(nullptr) {} explicit RepeatedPtrFieldBase(Arena* arena) : tagged_rep_or_elem_(nullptr), current_size_(0), - total_size_(kSSOCapacity), + capacity_proxy_(0), arena_(arena) {} RepeatedPtrFieldBase(const RepeatedPtrFieldBase&) = delete; @@ -198,7 +198,13 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { bool empty() const { return current_size_ == 0; } int size() const { return current_size_; } - int Capacity() const { return total_size_; } + // Returns the size of the buffer with pointers to elements. + // + // Note: + // + // * prefer `SizeAtCapacity()` to `size() == Capacity()`; + // * prefer `AllocatedSizeAtCapacity()` to `allocated_size() == Capacity()`. + int Capacity() const { return capacity_proxy_ + kSSOCapacity; } template const Value& at(int index) const { @@ -271,7 +277,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { } if (!using_sso()) { internal::SizedDelete(rep(), - total_size_ * sizeof(elems[0]) + kRepHeaderSize); + Capacity() * sizeof(elems[0]) + kRepHeaderSize); } } @@ -311,9 +317,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // Message creating functor: used in MergeFrom() template static MessageLite* CopyMessage(Arena* arena, const MessageLite& src) { - T* msg = Arena::CreateMaybeMessage(arena); - msg->MergeFrom(static_cast(src)); - return msg; + return Arena::CreateMaybeMessage(arena, static_cast(src)); } // Appends all message values from `from` to this instance. @@ -419,7 +423,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { size_t allocated_bytes = using_sso() ? 0 - : static_cast(total_size_) * sizeof(void*) + kRepHeaderSize; + : static_cast(Capacity()) * sizeof(void*) + kRepHeaderSize; const int n = allocated_size(); void* const* elems = elements(); for (int i = 0; i < n; ++i) { @@ -445,17 +449,19 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { template void AddAllocated(Value* value) { typename TypeImplementsMergeBehavior>::type t; + ABSL_DCHECK_NE(value, nullptr); AddAllocatedInternal(value, t); } template void UnsafeArenaAddAllocated(Value* value) { + ABSL_DCHECK_NE(value, nullptr); // Make room for the new pointer. - if (current_size_ == total_size_) { + if (SizeAtCapacity()) { // The array is completely full with no cleared objects, so grow it. - Reserve(total_size_ + 1); + InternalExtend(1); ++rep()->allocated_size; - } else if (allocated_size() == total_size_) { + } else if (AllocatedSizeAtCapacity()) { // There is no more space in the pointer array because it contains some // cleared objects awaiting reuse. We don't want to grow the array in // this case because otherwise a loop calling AddAllocated() followed by @@ -539,41 +545,41 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { void AddAllocatedInternal(Value* value, std::true_type) { Arena* element_arena = TypeHandler::GetArena(value); Arena* arena = GetArena(); - if (arena == element_arena && allocated_size() < total_size_) { - // Fast path: underlying arena representation (tagged pointer) is equal to - // our arena pointer, and we can add to array without resizing it (at - // least one slot that is not allocated). - void** elems = elements(); - if (current_size_ < allocated_size()) { - // Make space at [current] by moving first allocated element to end of - // allocated list. - elems[allocated_size()] = elems[current_size_]; - } - elems[ExchangeCurrentSize(current_size_ + 1)] = value; - if (!using_sso()) ++rep()->allocated_size; - } else { + if (arena != element_arena || AllocatedSizeAtCapacity()) { AddAllocatedSlowWithCopy(value, element_arena, arena); + return; + } + // Fast path: underlying arena representation (tagged pointer) is equal to + // our arena pointer, and we can add to array without resizing it (at + // least one slot that is not allocated). + void** elems = elements(); + if (current_size_ < allocated_size()) { + // Make space at [current] by moving first allocated element to end of + // allocated list. + elems[allocated_size()] = elems[current_size_]; } + elems[ExchangeCurrentSize(current_size_ + 1)] = value; + if (!using_sso()) ++rep()->allocated_size; } // AddAllocated version that does not implement arena-safe copying behavior. template void AddAllocatedInternal(Value* value, std::false_type) { - if (allocated_size() < total_size_) { - // Fast path: underlying arena representation (tagged pointer) is equal to - // our arena pointer, and we can add to array without resizing it (at - // least one slot that is not allocated). - void** elems = elements(); - if (current_size_ < allocated_size()) { - // Make space at [current] by moving first allocated element to end of - // allocated list. - elems[allocated_size()] = elems[current_size_]; - } - elems[ExchangeCurrentSize(current_size_ + 1)] = value; - if (!using_sso()) ++rep()->allocated_size; - } else { + if (AllocatedSizeAtCapacity()) { UnsafeArenaAddAllocated(value); + return; } + // Fast path: underlying arena representation (tagged pointer) is equal to + // our arena pointer, and we can add to array without resizing it (at + // least one slot that is not allocated). + void** elems = elements(); + if (current_size_ < allocated_size()) { + // Make space at [current] by moving first allocated element to end of + // allocated list. + elems[allocated_size()] = elems[current_size_]; + } + elems[ExchangeCurrentSize(current_size_ + 1)] = value; + if (!using_sso()) ++rep()->allocated_size; } // Slowpath handles all cases, copying if necessary. @@ -651,8 +657,6 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // Gets the Arena on which this RepeatedPtrField stores its elements. inline Arena* GetArena() const { return arena_; } - inline Arena* GetOwningArena() const { return arena_; } - private: using InternalArenaConstructable_ = void; using DestructorSkippable_ = void; @@ -717,6 +721,25 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { inline int ExchangeCurrentSize(int new_size) { return std::exchange(current_size_, new_size); } + inline bool SizeAtCapacity() const { + // Harden invariant size() <= allocated_size() <= Capacity(). + ABSL_DCHECK_LE(size(), allocated_size()); + ABSL_DCHECK_LE(allocated_size(), Capacity()); + // This is equivalent to `current_size_ == Capacity()`. + // Assuming `Capacity()` function is inlined, compiler is likely to optimize + // away "+ kSSOCapacity" and reduce it to "current_size_ > capacity_proxy_" + // which is an instruction less than "current_size_ == capacity_proxy_ + 1". + return current_size_ >= Capacity(); + } + inline bool AllocatedSizeAtCapacity() const { + // Harden invariant size() <= allocated_size() <= Capacity(). + ABSL_DCHECK_LE(size(), allocated_size()); + ABSL_DCHECK_LE(allocated_size(), Capacity()); + // This combines optimization mentioned in `SizeAtCapacity()` and simplifies + // `allocated_size()` in sso case. + return using_sso() ? (tagged_rep_or_elem_ != nullptr) + : rep()->allocated_size >= Capacity(); + } void* const* elements() const { return using_sso() ? &tagged_rep_or_elem_ : +rep()->elements; @@ -802,8 +825,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // Ensures that capacity is big enough to store one more allocated element. inline void MaybeExtend() { - if (using_sso() ? (tagged_rep_or_elem_ != nullptr) - : (rep()->allocated_size == total_size_)) { + if (AllocatedSizeAtCapacity()) { ABSL_DCHECK_EQ(allocated_size(), Capacity()); InternalExtend(1); } else { @@ -814,11 +836,11 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // Ensures that capacity is at least `n` elements. // Returns a pointer to the element directly beyond the last element. inline void** InternalReserve(int n) { - if (n <= total_size_) { + if (n <= Capacity()) { void** elements = using_sso() ? &tagged_rep_or_elem_ : rep()->elements; return elements + current_size_; } - return InternalExtend(n - total_size_); + return InternalExtend(n - Capacity()); } // Internal helper for Add: adds "obj" as the next element in the @@ -840,7 +862,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // significant performance for memory-sensitive workloads. void* tagged_rep_or_elem_; int current_size_; - int total_size_; + int capacity_proxy_; // we store `capacity - kSSOCapacity` as an optimization Arena* arena_; }; @@ -1099,13 +1121,13 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { // Calling this routine inside a loop can cause quadratic behavior. void DeleteSubrange(int start, int num); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear(); + ABSL_ATTRIBUTE_REINITIALIZES void Clear(); void MergeFrom(const RepeatedPtrField& other); - PROTOBUF_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedPtrField& other); + ABSL_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedPtrField& other); // Replaces the contents with RepeatedPtrField(begin, end). template - PROTOBUF_ATTRIBUTE_REINITIALIZES void Assign(Iter begin, Iter end); + ABSL_ATTRIBUTE_REINITIALIZES void Assign(Iter begin, Iter end); // Reserves space to expand the field to at least the given size. This only // resizes the pointer array; it doesn't allocate any objects. If the @@ -1181,6 +1203,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { // (ii) if this field holds strings, the passed-in string *must* be // heap-allocated, not arena-allocated. There is no way to dynamically check // this at runtime, so User Beware. + // Requires: value != nullptr void AddAllocated(Element* value); // Removes and returns the last element, passing ownership to the caller. @@ -1203,6 +1226,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { // If you put temp_field on the arena this fails, because the ownership // transfers to the arena at the "AddAllocated" call and is not released // anymore, causing a double delete. UnsafeArenaAddAllocated prevents this. + // Requires: value != nullptr void UnsafeArenaAddAllocated(Element* value); // Removes and returns the last element. Unlike ReleaseLast, the returned @@ -1315,9 +1339,6 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { RepeatedPtrField(Arena* arena, const RepeatedPtrField& rhs); - // Internal version of GetArena(). - inline Arena* GetOwningArena() const; - // Implementations for ExtractSubrange(). The copying behavior must be // included only if the type supports the necessary operations (e.g., @@ -1674,11 +1695,6 @@ inline Arena* RepeatedPtrField::GetArena() const { } #endif // !PROTOBUF_FUTURE_REMOVE_CONST_REPEATEDFIELD_GETARENA_API -template -inline Arena* RepeatedPtrField::GetOwningArena() const { - return RepeatedPtrFieldBase::GetArena(); -} - template inline size_t RepeatedPtrField::SpaceUsedExcludingSelfLong() const { // `google::protobuf::Message` has a virtual method `SpaceUsedLong`, hence we can diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index d22acee088..b93bf206fa 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -50,28 +50,30 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceContext, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceContext, _impl_.file_name_), +const ::uint32_t + TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceContext, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceContext, _impl_.file_name_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, -1, -1, sizeof(::google::protobuf::SourceContext)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_SourceContext_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n$google/protobuf/source_context.proto\022\017" "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile" "_name\030\001 \001(\tB\212\001\n\023com.google.protobufB\022Sou" @@ -166,6 +168,16 @@ inline void SourceContext::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +SourceContext::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + SourceContext::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void SourceContext::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -258,13 +270,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 47, 2> SourceContext::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData SourceContext::_class_data_ = { - SourceContext::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* SourceContext::GetClassData() const { - return &_class_data_; -} void SourceContext::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h index 9d35f1b2dd..fcfd373ae9 100644 --- a/src/google/protobuf/source_context.pb.h +++ b/src/google/protobuf/source_context.pb.h @@ -168,7 +168,7 @@ class PROTOBUF_EXPORT SourceContext final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -191,11 +191,9 @@ class PROTOBUF_EXPORT SourceContext final : protected: explicit SourceContext(::google::protobuf::Arena* arena); SourceContext(::google::protobuf::Arena* arena, const SourceContext& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index 2a20dd6918..cb8e5c9736 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -98,57 +98,58 @@ static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fstruct_2eproto[4] static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto[1]; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, key_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, value_), - 0, - 1, - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct, _impl_.fields_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Value, _internal_metadata_), - ~0u, // no _extensions_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Value, _impl_._oneof_case_[0]), - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - ::_pbi::kInvalidFieldOffsetTag, - ::_pbi::kInvalidFieldOffsetTag, - ::_pbi::kInvalidFieldOffsetTag, - ::_pbi::kInvalidFieldOffsetTag, - ::_pbi::kInvalidFieldOffsetTag, - ::_pbi::kInvalidFieldOffsetTag, - PROTOBUF_FIELD_OFFSET(::google::protobuf::Value, _impl_.kind_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::ListValue, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::ListValue, _impl_.values_), +const ::uint32_t + TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, key_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, value_), + 0, + 1, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct, _impl_.fields_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Value, _internal_metadata_), + ~0u, // no _extensions_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Value, _impl_._oneof_case_[0]), + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + PROTOBUF_FIELD_OFFSET(::google::protobuf::Value, _impl_.kind_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::ListValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::ListValue, _impl_.values_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, 10, -1, sizeof(::google::protobuf::Struct_FieldsEntry_DoNotUse)}, {12, -1, -1, sizeof(::google::protobuf::Struct)}, {21, -1, -1, sizeof(::google::protobuf::Value)}, @@ -161,7 +162,8 @@ static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Value_default_instance_._instance, &::google::protobuf::_ListValue_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\034google/protobuf/struct.proto\022\017google.p" "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo" "gle.protobuf.Struct.FieldsEntry\032E\n\013Field" @@ -284,6 +286,16 @@ inline void Struct::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Struct::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Struct::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Struct::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Struct) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -398,13 +410,6 @@ const ::_pbi::TcParseTable<0, 1, 2, 37, 2> Struct::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Struct::_class_data_ = { - Struct::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Struct::GetClassData() const { - return &_class_data_; -} void Struct::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -594,6 +599,16 @@ void Value::clear_kind() { } +const ::google::protobuf::MessageLite::ClassData* +Value::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Value::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Value::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Value) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -766,13 +781,6 @@ const ::_pbi::TcParseTable<0, 6, 2, 42, 2> Value::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Value::_class_data_ = { - Value::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Value::GetClassData() const { - return &_class_data_; -} void Value::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -890,6 +898,16 @@ inline void ListValue::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +ListValue::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + ListValue::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void ListValue::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -979,13 +997,6 @@ const ::_pbi::TcParseTable<0, 1, 1, 0, 2> ListValue::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData ListValue::_class_data_ = { - ListValue::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* ListValue::GetClassData() const { - return &_class_data_; -} void ListValue::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index ef2b036ff6..5fdf8c0578 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -213,7 +213,7 @@ class PROTOBUF_EXPORT ListValue final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -236,11 +236,9 @@ class PROTOBUF_EXPORT ListValue final : protected: explicit ListValue(::google::protobuf::Arena* arena); ListValue(::google::protobuf::Arena* arena, const ListValue& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -396,7 +394,7 @@ class PROTOBUF_EXPORT Struct final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -419,11 +417,9 @@ class PROTOBUF_EXPORT Struct final : protected: explicit Struct(::google::protobuf::Arena* arena); Struct(::google::protobuf::Arena* arena, const Struct& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -618,7 +614,7 @@ class PROTOBUF_EXPORT Value final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -641,11 +637,9 @@ class PROTOBUF_EXPORT Value final : protected: explicit Value(::google::protobuf::Arena* arena); Value(::google::protobuf::Arena* arena, const Value& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/stubs/BUILD.bazel b/src/google/protobuf/stubs/BUILD.bazel index 740e43e815..f89f34a004 100644 --- a/src/google/protobuf/stubs/BUILD.bazel +++ b/src/google/protobuf/stubs/BUILD.bazel @@ -22,8 +22,8 @@ cc_library( "status_macros.h", ], copts = COPTS, - include_prefix = "google/protobuf/stubs", linkopts = LINK_OPTS, + strip_include_prefix = "/src", deps = [ "//src/google/protobuf:port_def", "@com_google_absl//absl/log:absl_log", @@ -40,7 +40,7 @@ cc_library( hdrs = [ ], copts = COPTS, - include_prefix = "google/protobuf/stubs", + strip_include_prefix = "/src", textual_hdrs = [ "callback.h", "common.h", diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc index a61cbd2404..faff493a4e 100644 --- a/src/google/protobuf/stubs/common.cc +++ b/src/google/protobuf/stubs/common.cc @@ -120,10 +120,6 @@ void DoNothing() {} // =================================================================== // emulates google3/util/endian/endian.h -// -// TODO: PROTOBUF_LITTLE_ENDIAN is unfortunately defined in -// google/protobuf/io/coded_stream.h and therefore can not be used here. -// Maybe move that macro definition here in the future. uint32_t ghtonl(uint32_t x) { union { uint32_t result; diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h index 4a38c372fa..cd4025f6ae 100644 --- a/src/google/protobuf/stubs/port.h +++ b/src/google/protobuf/stubs/port.h @@ -21,42 +21,6 @@ // Must be last. #include "google/protobuf/port_def.inc" // NOLINT -#undef PROTOBUF_LITTLE_ENDIAN -#ifdef _WIN32 - // Assuming windows is always little-endian. - // TODO: The PROTOBUF_LITTLE_ENDIAN is not only used for - // optimization but also for correctness. We should define an - // different macro to test the big-endian code path in coded_stream. - #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) - #define PROTOBUF_LITTLE_ENDIAN 1 - #endif -#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) -// If MSVC has "/RTCc" set, it will complain about truncating casts at -// runtime. This file contains some intentional truncating casts. -#pragma runtime_checks("c", off) -#endif -#else -#if (defined(__APPLE__) || defined(__NEWLIB__)) -#include // __BYTE_ORDER -#elif defined(__FreeBSD__) -#include // __BYTE_ORDER -#elif (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__)) -#include // __BYTE_ORDER -#elif defined(_AIX) || defined(__TOS_AIX__) -#include // BYTE_ORDER -#elif defined(__QNX__) -#include // BYTE_ORDER -#else -#include // __BYTE_ORDER -#endif -#if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ - (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \ - !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) -#define PROTOBUF_LITTLE_ENDIAN 1 -#endif -#endif - // These #includes are for the byte swap functions declared later on. #ifdef _MSC_VER #include // NOLINT(build/include) @@ -212,7 +176,7 @@ PROTOBUF_EXPORT uint32_t ghtonl(uint32_t x); class BigEndian { public: -#ifdef PROTOBUF_LITTLE_ENDIAN +#ifdef ABSL_IS_LITTLE_ENDIAN static uint16_t FromHost16(uint16_t x) { return bswap_16(x); } static uint16_t ToHost16(uint16_t x) { return bswap_16(x); } diff --git a/src/google/protobuf/testing/BUILD.bazel b/src/google/protobuf/testing/BUILD.bazel index 572c1f9f46..ab3e979d91 100644 --- a/src/google/protobuf/testing/BUILD.bazel +++ b/src/google/protobuf/testing/BUILD.bazel @@ -19,8 +19,8 @@ cc_library( "googletest.h", ], copts = COPTS, - include_prefix = "google/protobuf/testing", linkopts = LINK_OPTS, + strip_include_prefix = "/src", deps = [ "//:protobuf_lite", # for ShutdownProtobufLibrary "//src/google/protobuf/io", diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index f5df44215a..9abd84772a 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -2769,7 +2769,12 @@ void TextFormat::Printer::PrintUnknownFields( case UnknownField::TYPE_VARINT: OutOfLinePrintString(generator, field.number()); generator->PrintMaybeWithMarker(MarkerToken(), ": "); - OutOfLinePrintString(generator, field.varint()); + if (redact_debug_string_) { + OutOfLinePrintString(generator, "UNKNOWN_VARINT "); + OutOfLinePrintString(generator, kFieldValueReplacement); + } else { + OutOfLinePrintString(generator, field.varint()); + } if (single_line_mode_) { generator->PrintLiteral(" "); } else { @@ -2778,9 +2783,15 @@ void TextFormat::Printer::PrintUnknownFields( break; case UnknownField::TYPE_FIXED32: { OutOfLinePrintString(generator, field.number()); - generator->PrintMaybeWithMarker(MarkerToken(), ": ", "0x"); - OutOfLinePrintString(generator, - absl::Hex(field.fixed32(), absl::kZeroPad8)); + if (redact_debug_string_) { + generator->PrintMaybeWithMarker(MarkerToken(), ": ", + "UNKNOWN_FIXED32 "); + OutOfLinePrintString(generator, kFieldValueReplacement); + } else { + generator->PrintMaybeWithMarker(MarkerToken(), ": ", "0x"); + OutOfLinePrintString(generator, + absl::Hex(field.fixed32(), absl::kZeroPad8)); + } if (single_line_mode_) { generator->PrintLiteral(" "); } else { @@ -2790,9 +2801,15 @@ void TextFormat::Printer::PrintUnknownFields( } case UnknownField::TYPE_FIXED64: { OutOfLinePrintString(generator, field.number()); - generator->PrintMaybeWithMarker(MarkerToken(), ": ", "0x"); - OutOfLinePrintString(generator, - absl::Hex(field.fixed64(), absl::kZeroPad16)); + if (redact_debug_string_) { + generator->PrintMaybeWithMarker(MarkerToken(), ": ", + "UNKNOWN_FIXED64 "); + OutOfLinePrintString(generator, kFieldValueReplacement); + } else { + generator->PrintMaybeWithMarker(MarkerToken(), ": ", "0x"); + OutOfLinePrintString(generator, + absl::Hex(field.fixed64(), absl::kZeroPad16)); + } if (single_line_mode_) { generator->PrintLiteral(" "); } else { @@ -2814,6 +2831,17 @@ void TextFormat::Printer::PrintUnknownFields( embedded_unknown_fields.ParseFromCodedStream(&input_stream)) { // This field is parseable as a Message. // So it is probably an embedded message. + if (redact_debug_string_) { + generator->PrintMaybeWithMarker(MarkerToken(), ": ", + "UNKNOWN_MESSAGE "); + OutOfLinePrintString(generator, kFieldValueReplacement); + if (single_line_mode_) { + generator->PrintLiteral(" "); + } else { + generator->PrintLiteral("\n"); + } + break; + } if (single_line_mode_) { generator->PrintMaybeWithMarker(MarkerToken(), " ", "{ "); } else { @@ -2831,6 +2859,17 @@ void TextFormat::Printer::PrintUnknownFields( } else { // This field is not parseable as a Message (or we ran out of // recursion budget). So it is probably just a plain string. + if (redact_debug_string_) { + generator->PrintMaybeWithMarker(MarkerToken(), ": ", + "UNKNOWN_STRING "); + OutOfLinePrintString(generator, kFieldValueReplacement); + if (single_line_mode_) { + generator->PrintLiteral(" "); + } else { + generator->PrintLiteral("\n"); + } + break; + } generator->PrintMaybeWithMarker(MarkerToken(), ": ", "\""); generator->PrintString(absl::CEscape(value)); if (single_line_mode_) { @@ -2843,6 +2882,17 @@ void TextFormat::Printer::PrintUnknownFields( } case UnknownField::TYPE_GROUP: OutOfLinePrintString(generator, field.number()); + if (redact_debug_string_) { + generator->PrintMaybeWithMarker(MarkerToken(), ": ", + "UNKNOWN_GROUP "); + OutOfLinePrintString(generator, kFieldValueReplacement); + if (single_line_mode_) { + generator->PrintLiteral(" "); + } else { + generator->PrintLiteral("\n"); + } + break; + } if (single_line_mode_) { generator->PrintMaybeWithMarker(MarkerToken(), " ", "{ "); } else { diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index 0ac3ab7265..9f60c9f3fd 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -69,6 +69,8 @@ constexpr absl::string_view kEscapeTestStringEscaped = "\"\\\"A string with \\' characters \\n and \\r newlines " "and \\t tabs and \\001 slashes \\\\ and multiple spaces\""; +constexpr absl::string_view value_replacement = "\\[REDACTED\\]"; + class TextFormatTest : public testing::Test { public: static void SetUpTestSuite() { @@ -172,35 +174,24 @@ TEST_F(TextFormatTest, ShortFormat) { std::string value_replacement = "\\[REDACTED\\]"; EXPECT_THAT(google::protobuf::ShortFormat(proto), - testing::MatchesRegex( - "optional_redacted_string: " + - value_replacement + - " " + testing::MatchesRegex(absl::Substitute( + "optional_redacted_string: $0 " "optional_unredacted_string: \"bar\" " - "repeated_redacted_string: " + - value_replacement + - " " - "repeated_redacted_string: " + - value_replacement + - " " + "repeated_redacted_string: $0 " + "repeated_redacted_string: $0 " "repeated_unredacted_string: \"3\" " "repeated_unredacted_string: \"4\" " - "optional_redacted_message: " + - value_replacement + - " " + "optional_redacted_message: $0 " "optional_unredacted_message \\{ " "optional_unredacted_nested_string: \"world\" \\} " - "repeated_redacted_message: " + - value_replacement + - " " + "repeated_redacted_message: $0 " "repeated_unredacted_message " "\\{ optional_unredacted_nested_string: \"7\" \\} " "repeated_unredacted_message " "\\{ optional_unredacted_nested_string: \"8\" \\} " - "map_redacted_string: " + - value_replacement + - " " - "map_unredacted_string \\{ key: \"ghi\" value: \"jkl\" \\}")); + "map_redacted_string: $0 " + "map_unredacted_string \\{ key: \"ghi\" value: \"jkl\" \\}", + value_replacement))); } TEST_F(TextFormatTest, Utf8Format) { @@ -234,39 +225,27 @@ TEST_F(TextFormatTest, Utf8Format) { (*proto.mutable_map_redacted_string())["abc"] = "def"; (*proto.mutable_map_unredacted_string())["ghi"] = "jkl"; - std::string value_replacement = "\\[REDACTED\\]"; EXPECT_THAT(google::protobuf::Utf8Format(proto), - testing::MatchesRegex( - "optional_redacted_string: " + - value_replacement + - "\n" + testing::MatchesRegex(absl::Substitute( + "optional_redacted_string: $0\n" "optional_unredacted_string: \"bar\"\n" - "repeated_redacted_string: " + - value_replacement + - "\n" - "repeated_redacted_string: " + - value_replacement + - "\n" + "repeated_redacted_string: $0\n" + "repeated_redacted_string: $0\n" "repeated_unredacted_string: \"3\"\n" "repeated_unredacted_string: \"4\"\n" - "optional_redacted_message: " + - value_replacement + - "\n" + "optional_redacted_message: $0\n" "optional_unredacted_message \\{\n " "optional_unredacted_nested_string: " "\"\xE8\xB0\xB7\xE6\xAD\x8C\"\n\\}\n" - "repeated_redacted_message: " + - value_replacement + - "\n" + "repeated_redacted_message: $0\n" "repeated_unredacted_message \\{\n " "optional_unredacted_nested_string: \"7\"\n\\}\n" "repeated_unredacted_message \\{\n " "optional_unredacted_nested_string: \"8\"\n\\}\n" - "map_redacted_string: " + - value_replacement + - "\n" + "map_redacted_string: $0\n" "map_unredacted_string \\{\n " - "key: \"ghi\"\n value: \"jkl\"\n\\}\n")); + "key: \"ghi\"\n value: \"jkl\"\n\\}\n", + value_replacement))); } TEST_F(TextFormatTest, ShortPrimitiveRepeateds) { @@ -402,6 +381,17 @@ TEST_F(TextFormatTest, PrintUnknownFields) { "8: 2\n" "8: 3\n"), message.DebugString()); + + EXPECT_THAT(absl::StrCat(message), testing::MatchesRegex(absl::Substitute( + "5: UNKNOWN_VARINT $0\n" + "5: UNKNOWN_FIXED32 $0\n" + "5: UNKNOWN_FIXED64 $0\n" + "5: UNKNOWN_STRING $0\n" + "5: UNKNOWN_GROUP $0\n" + "8: UNKNOWN_VARINT $0\n" + "8: UNKNOWN_VARINT $0\n" + "8: UNKNOWN_VARINT $0\n", + value_replacement))); } TEST_F(TextFormatTest, PrintUnknownFieldsDeepestStackWorks) { diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 668dbf3ed7..e048cb8c30 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -49,29 +49,31 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _impl_.seconds_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _impl_.nanos_), +const ::uint32_t + TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _impl_.seconds_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _impl_.nanos_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, -1, -1, sizeof(::google::protobuf::Timestamp)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Timestamp_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\037google/protobuf/timestamp.proto\022\017googl" "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003" "\022\r\n\005nanos\030\002 \001(\005B\205\001\n\023com.google.protobufB" @@ -157,6 +159,16 @@ inline void Timestamp::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Timestamp::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Timestamp::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Timestamp::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -266,13 +278,6 @@ const ::_pbi::TcParseTable<1, 2, 0, 0, 2> Timestamp::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Timestamp::_class_data_ = { - Timestamp::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Timestamp::GetClassData() const { - return &_class_data_; -} void Timestamp::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h index 9a65792520..6c3d37a117 100644 --- a/src/google/protobuf/timestamp.pb.h +++ b/src/google/protobuf/timestamp.pb.h @@ -168,7 +168,7 @@ class PROTOBUF_EXPORT Timestamp final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -191,11 +191,9 @@ class PROTOBUF_EXPORT Timestamp final : protected: explicit Timestamp(::google::protobuf::Arena* arena); Timestamp(::google::protobuf::Arena* arena, const Timestamp& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 2bcd7e1760..29884227e7 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -166,95 +166,96 @@ static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2ftype_2eproto[5]; static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[3]; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2ftype_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.fields_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.oneofs_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.source_context_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.syntax_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.edition_), - ~0u, - ~0u, - ~0u, - ~0u, - 0, - ~0u, - ~0u, - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.kind_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.cardinality_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.number_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.type_url_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.oneof_index_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.packed_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.json_name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.default_value_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.enumvalue_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.source_context_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.syntax_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.edition_), - ~0u, - ~0u, - ~0u, - 0, - ~0u, - ~0u, - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.number_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.options_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_.value_), - ~0u, - 0, +const ::uint32_t + TableStruct_google_2fprotobuf_2ftype_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.fields_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.oneofs_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.source_context_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.syntax_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Type, _impl_.edition_), + ~0u, + ~0u, + ~0u, + ~0u, + 0, + ~0u, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.cardinality_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.type_url_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.oneof_index_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.packed_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.json_name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_.default_value_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.enumvalue_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.source_context_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.syntax_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_.edition_), + ~0u, + ~0u, + ~0u, + 0, + ~0u, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_.value_), + ~0u, + 0, }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, 15, -1, sizeof(::google::protobuf::Type)}, {22, -1, -1, sizeof(::google::protobuf::Field)}, {40, 54, -1, sizeof(::google::protobuf::Enum)}, @@ -269,7 +270,8 @@ static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_EnumValue_default_instance_._instance, &::google::protobuf::_Option_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\032google/protobuf/type.proto\022\017google.pro" "tobuf\032\031google/protobuf/any.proto\032$google" "/protobuf/source_context.proto\"\350\001\n\004Type\022" @@ -510,6 +512,16 @@ inline void Type::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Type::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Type::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Type::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Type) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -738,13 +750,6 @@ const ::_pbi::TcParseTable<3, 7, 3, 46, 2> Type::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Type::_class_data_ = { - Type::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Type::GetClassData() const { - return &_class_data_; -} void Type::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -886,6 +891,16 @@ inline void Field::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Field::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Field::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Field::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Field) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1168,13 +1183,6 @@ const ::_pbi::TcParseTable<4, 10, 1, 72, 2> Field::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Field::_class_data_ = { - Field::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Field::GetClassData() const { - return &_class_data_; -} void Field::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1337,6 +1345,16 @@ inline void Enum::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Enum::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Enum::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Enum::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Enum) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1544,13 +1562,6 @@ const ::_pbi::TcParseTable<3, 6, 3, 40, 2> Enum::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Enum::_class_data_ = { - Enum::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Enum::GetClassData() const { - return &_class_data_; -} void Enum::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1670,6 +1681,16 @@ inline void EnumValue::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +EnumValue::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + EnumValue::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void EnumValue::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1804,13 +1825,6 @@ const ::_pbi::TcParseTable<2, 3, 1, 38, 2> EnumValue::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData EnumValue::_class_data_ = { - EnumValue::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* EnumValue::GetClassData() const { - return &_class_data_; -} void EnumValue::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1931,6 +1945,16 @@ inline void Option::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Option::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Option::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Option::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Option) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -2050,13 +2074,6 @@ const ::_pbi::TcParseTable<1, 2, 1, 35, 2> Option::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Option::_class_data_ = { - Option::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Option::GetClassData() const { - return &_class_data_; -} void Option::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h index 0ff5349da9..beda8737f8 100644 --- a/src/google/protobuf/type.pb.h +++ b/src/google/protobuf/type.pb.h @@ -302,7 +302,7 @@ class PROTOBUF_EXPORT Option final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -325,11 +325,9 @@ class PROTOBUF_EXPORT Option final : protected: explicit Option(::google::protobuf::Arena* arena); Option(::google::protobuf::Arena* arena, const Option& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -501,7 +499,7 @@ class PROTOBUF_EXPORT Field final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -524,11 +522,9 @@ class PROTOBUF_EXPORT Field final : protected: explicit Field(::google::protobuf::Arena* arena); Field(::google::protobuf::Arena* arena, const Field& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -875,7 +871,7 @@ class PROTOBUF_EXPORT EnumValue final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -898,11 +894,9 @@ class PROTOBUF_EXPORT EnumValue final : protected: explicit EnumValue(::google::protobuf::Arena* arena); EnumValue(::google::protobuf::Arena* arena, const EnumValue& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1088,7 +1082,7 @@ class PROTOBUF_EXPORT Type final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1111,11 +1105,9 @@ class PROTOBUF_EXPORT Type final : protected: explicit Type(::google::protobuf::Arena* arena); Type(::google::protobuf::Arena* arena, const Type& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1387,7 +1379,7 @@ class PROTOBUF_EXPORT Enum final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1410,11 +1402,9 @@ class PROTOBUF_EXPORT Enum final : protected: explicit Enum(::google::protobuf::Arena* arena); Enum(::google::protobuf::Arena* arena, const Enum& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc index ff1ed9ee07..dcd20e5ad6 100644 --- a/src/google/protobuf/unknown_field_set_unittest.cc +++ b/src/google/protobuf/unknown_field_set_unittest.cc @@ -614,15 +614,15 @@ TEST_F(UnknownFieldSetTest, DeleteSubrange) { void CheckDeleteByNumber(const std::vector& field_numbers, int deleted_number, - const std::vector& expected_field_nubmers) { + const std::vector& expected_field_numbers) { UnknownFieldSet unknown_fields; for (int i = 0; i < field_numbers.size(); ++i) { unknown_fields.AddFixed32(field_numbers[i], i); } unknown_fields.DeleteByNumber(deleted_number); - ASSERT_EQ(expected_field_nubmers.size(), unknown_fields.field_count()); - for (int i = 0; i < expected_field_nubmers.size(); ++i) { - EXPECT_EQ(expected_field_nubmers[i], unknown_fields.field(i).number()); + ASSERT_EQ(expected_field_numbers.size(), unknown_fields.field_count()); + for (int i = 0; i < expected_field_numbers.size(); ++i) { + EXPECT_EQ(expected_field_numbers[i], unknown_fields.field(i).number()); } } diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index 4526417192..bbd012d23c 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -960,7 +960,7 @@ const char* WireFormat::_InternalParseAndMergeField( case FieldDescriptor::TYPE_STRING: utf8_check = true; strict_utf8_check = field->requires_utf8_validation(); - PROTOBUF_FALLTHROUGH_INTENDED; + ABSL_FALLTHROUGH_INTENDED; case FieldDescriptor::TYPE_BYTES: { int size = ReadSize(&ptr); if (ptr == nullptr) return nullptr; diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc index d3eb12bbca..2fd31426ce 100644 --- a/src/google/protobuf/wire_format_lite.cc +++ b/src/google/protobuf/wire_format_lite.cc @@ -303,7 +303,7 @@ bool WireFormatLite::ReadPackedEnumPreserveUnknowns( return true; } -#if !defined(PROTOBUF_LITTLE_ENDIAN) +#if !defined(ABSL_IS_LITTLE_ENDIAN) namespace { void EncodeFixedSizeValue(float v, uint8_t* dest) { @@ -335,11 +335,11 @@ void EncodeFixedSizeValue(bool v, uint8_t* dest) { } } // anonymous namespace -#endif // !defined(PROTOBUF_LITTLE_ENDIAN) +#endif // !defined(ABSL_IS_LITTLE_ENDIAN) template static void WriteArray(const CType* a, int n, io::CodedOutputStream* output) { -#if defined(PROTOBUF_LITTLE_ENDIAN) +#if defined(ABSL_IS_LITTLE_ENDIAN) output->WriteRaw(reinterpret_cast(a), n * sizeof(a[0])); #else const int kAtATime = 128; diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h index ef368808c5..872c5ff02b 100644 --- a/src/google/protobuf/wire_format_lite.h +++ b/src/google/protobuf/wire_format_lite.h @@ -1206,7 +1206,7 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive( } if (bytes_limit >= new_bytes) { // Fast-path that pre-allocates *values to the final size. -#if defined(PROTOBUF_LITTLE_ENDIAN) +#if defined(ABSL_IS_LITTLE_ENDIAN) values->Resize(old_entries + new_entries, 0); // values->mutable_data() may change after Resize(), so do this after: void* dest = reinterpret_cast(values->mutable_data() + old_entries); @@ -1476,7 +1476,7 @@ template inline uint8_t* WireFormatLite::WriteFixedNoTagToArray( const RepeatedField& value, uint8_t* (*Writer)(T, uint8_t*), uint8_t* target) { -#if defined(PROTOBUF_LITTLE_ENDIAN) +#if defined(ABSL_IS_LITTLE_ENDIAN) (void)Writer; const int n = value.size(); diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index 18f64b7eda..cf7efbb562 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -204,93 +204,94 @@ static constexpr const ::_pb::EnumDescriptor** file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr; -const ::uint32_t TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( - protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::DoubleValue, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::DoubleValue, _impl_.value_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::FloatValue, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::FloatValue, _impl_.value_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Int64Value, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Int64Value, _impl_.value_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::UInt64Value, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::UInt64Value, _impl_.value_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::Int32Value, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::Int32Value, _impl_.value_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::UInt32Value, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::UInt32Value, _impl_.value_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::BoolValue, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::BoolValue, _impl_.value_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::StringValue, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::StringValue, _impl_.value_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::google::protobuf::BytesValue, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::google::protobuf::BytesValue, _impl_.value_), +const ::uint32_t + TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::DoubleValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::DoubleValue, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::FloatValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::FloatValue, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Int64Value, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Int64Value, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::UInt64Value, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::UInt64Value, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::Int32Value, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::Int32Value, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::UInt32Value, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::UInt32Value, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::BoolValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::BoolValue, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::StringValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::StringValue, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::BytesValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::google::protobuf::BytesValue, _impl_.value_), }; static const ::_pbi::MigrationSchema - schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { {0, -1, -1, sizeof(::google::protobuf::DoubleValue)}, {9, -1, -1, sizeof(::google::protobuf::FloatValue)}, {18, -1, -1, sizeof(::google::protobuf::Int64Value)}, @@ -313,7 +314,8 @@ static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_StringValue_default_instance_._instance, &::google::protobuf::_BytesValue_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { +const char descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { "\n\036google/protobuf/wrappers.proto\022\017google" ".protobuf\"\034\n\013DoubleValue\022\r\n\005value\030\001 \001(\001\"" "\033\n\nFloatValue\022\r\n\005value\030\001 \001(\002\"\033\n\nInt64Val" @@ -400,6 +402,16 @@ inline void DoubleValue::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +DoubleValue::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + DoubleValue::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void DoubleValue::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -497,13 +509,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> DoubleValue::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData DoubleValue::_class_data_ = { - DoubleValue::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* DoubleValue::GetClassData() const { - return &_class_data_; -} void DoubleValue::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -584,6 +589,16 @@ inline void FloatValue::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +FloatValue::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + FloatValue::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void FloatValue::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -681,13 +696,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> FloatValue::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData FloatValue::_class_data_ = { - FloatValue::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* FloatValue::GetClassData() const { - return &_class_data_; -} void FloatValue::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -768,6 +776,16 @@ inline void Int64Value::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Int64Value::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Int64Value::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Int64Value::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -856,13 +874,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> Int64Value::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Int64Value::_class_data_ = { - Int64Value::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Int64Value::GetClassData() const { - return &_class_data_; -} void Int64Value::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -938,6 +949,16 @@ inline void UInt64Value::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +UInt64Value::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + UInt64Value::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void UInt64Value::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1026,13 +1047,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> UInt64Value::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData UInt64Value::_class_data_ = { - UInt64Value::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* UInt64Value::GetClassData() const { - return &_class_data_; -} void UInt64Value::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1108,6 +1122,16 @@ inline void Int32Value::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +Int32Value::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + Int32Value::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void Int32Value::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1196,13 +1220,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> Int32Value::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData Int32Value::_class_data_ = { - Int32Value::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* Int32Value::GetClassData() const { - return &_class_data_; -} void Int32Value::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1278,6 +1295,16 @@ inline void UInt32Value::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +UInt32Value::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + UInt32Value::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void UInt32Value::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1366,13 +1393,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> UInt32Value::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData UInt32Value::_class_data_ = { - UInt32Value::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* UInt32Value::GetClassData() const { - return &_class_data_; -} void UInt32Value::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1448,6 +1468,16 @@ inline void BoolValue::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +BoolValue::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + BoolValue::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void BoolValue::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1535,13 +1565,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> BoolValue::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData BoolValue::_class_data_ = { - BoolValue::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* BoolValue::GetClassData() const { - return &_class_data_; -} void BoolValue::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1631,6 +1654,16 @@ inline void StringValue::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +StringValue::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + StringValue::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void StringValue::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1723,13 +1756,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 41, 2> StringValue::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData StringValue::_class_data_ = { - StringValue::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* StringValue::GetClassData() const { - return &_class_data_; -} void StringValue::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1821,6 +1847,16 @@ inline void BytesValue::SharedDtor() { _impl_.~Impl_(); } +const ::google::protobuf::MessageLite::ClassData* +BytesValue::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite::ClassData + data = { + BytesValue::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor + &::google::protobuf::Message::kDescriptorMethods, + }; + return &data; +} PROTOBUF_NOINLINE void BytesValue::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue) PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); @@ -1908,13 +1944,6 @@ const ::_pbi::TcParseTable<0, 1, 0, 0, 2> BytesValue::_table_ = { return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); } -const ::google::protobuf::Message::ClassData BytesValue::_class_data_ = { - BytesValue::MergeImpl, - nullptr, // OnDemandRegisterArenaDtor -}; -const ::google::protobuf::Message::ClassData* BytesValue::GetClassData() const { - return &_class_data_; -} void BytesValue::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { auto* const _this = static_cast(&to_msg); diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h index b348b5d7c7..0973c4d940 100644 --- a/src/google/protobuf/wrappers.pb.h +++ b/src/google/protobuf/wrappers.pb.h @@ -192,7 +192,7 @@ class PROTOBUF_EXPORT UInt64Value final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -215,11 +215,9 @@ class PROTOBUF_EXPORT UInt64Value final : protected: explicit UInt64Value(::google::protobuf::Arena* arena); UInt64Value(::google::protobuf::Arena* arena, const UInt64Value& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -367,7 +365,7 @@ class PROTOBUF_EXPORT UInt32Value final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -390,11 +388,9 @@ class PROTOBUF_EXPORT UInt32Value final : protected: explicit UInt32Value(::google::protobuf::Arena* arena); UInt32Value(::google::protobuf::Arena* arena, const UInt32Value& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -542,7 +538,7 @@ class PROTOBUF_EXPORT StringValue final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -565,11 +561,9 @@ class PROTOBUF_EXPORT StringValue final : protected: explicit StringValue(::google::protobuf::Arena* arena); StringValue(::google::protobuf::Arena* arena, const StringValue& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -723,7 +717,7 @@ class PROTOBUF_EXPORT Int64Value final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -746,11 +740,9 @@ class PROTOBUF_EXPORT Int64Value final : protected: explicit Int64Value(::google::protobuf::Arena* arena); Int64Value(::google::protobuf::Arena* arena, const Int64Value& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -898,7 +890,7 @@ class PROTOBUF_EXPORT Int32Value final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -921,11 +913,9 @@ class PROTOBUF_EXPORT Int32Value final : protected: explicit Int32Value(::google::protobuf::Arena* arena); Int32Value(::google::protobuf::Arena* arena, const Int32Value& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1073,7 +1063,7 @@ class PROTOBUF_EXPORT FloatValue final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1096,11 +1086,9 @@ class PROTOBUF_EXPORT FloatValue final : protected: explicit FloatValue(::google::protobuf::Arena* arena); FloatValue(::google::protobuf::Arena* arena, const FloatValue& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1248,7 +1236,7 @@ class PROTOBUF_EXPORT DoubleValue final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1271,11 +1259,9 @@ class PROTOBUF_EXPORT DoubleValue final : protected: explicit DoubleValue(::google::protobuf::Arena* arena); DoubleValue(::google::protobuf::Arena* arena, const DoubleValue& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1423,7 +1409,7 @@ class PROTOBUF_EXPORT BytesValue final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1446,11 +1432,9 @@ class PROTOBUF_EXPORT BytesValue final : protected: explicit BytesValue(::google::protobuf::Arena* arena); BytesValue(::google::protobuf::Arena* arena, const BytesValue& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- @@ -1604,7 +1588,7 @@ class PROTOBUF_EXPORT BoolValue final : private: static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); public: - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; ::size_t ByteSizeLong() const final; @@ -1627,11 +1611,9 @@ class PROTOBUF_EXPORT BoolValue final : protected: explicit BoolValue(::google::protobuf::Arena* arena); BoolValue(::google::protobuf::Arena* arena, const BoolValue& from); + const ::google::protobuf::MessageLite::ClassData* GetClassData() const final; public: - static const ClassData _class_data_; - const ::google::protobuf::Message::ClassData*GetClassData() const final; - ::google::protobuf::Metadata GetMetadata() const final; // nested types ---------------------------------------------------- diff --git a/upb/BUILD b/upb/BUILD index 02d65bdee2..1e52a8092b 100644 --- a/upb/BUILD +++ b/upb/BUILD @@ -8,14 +8,7 @@ load("@rules_python//python:defs.bzl", "py_binary") load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") load("//bazel:build_defs.bzl", "UPB_DEFAULT_COPTS") -load("//bazel:upb_minitable_proto_library.bzl", "upb_minitable_proto_library") -load("//bazel:upb_proto_library.bzl", "upb_proto_reflection_library") load("//bazel:upb_proto_library_internal/copts.bzl", "upb_proto_library_copts") -load( - "//upb_generator:bootstrap_compiler.bzl", - "bootstrap_cc_library", - "bootstrap_upb_proto_library", -) # begin:google_only # load("//tools/build_defs/kotlin/native:rules.bzl", "kt_native_interop_hint") @@ -104,14 +97,14 @@ cc_library( # implementation, but depends on :upb and exposes a few more hdrs. # # This is public only because we have no way of visibility-limiting it to -# upb_proto_library() only. This interface is not stable and by using it you +# upb_c_proto_library() only. This interface is not stable and by using it you # give up any backward compatibility guarantees. cc_library( name = "generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", hdrs = ["generated_code_support.h"], copts = UPB_DEFAULT_COPTS, textual_hdrs = [ - "//upb/port:inc", + ":port_inc", ], visibility = ["//visibility:public"], deps = [ @@ -133,176 +126,54 @@ cc_library( name = "generated_cpp_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", copts = UPB_DEFAULT_COPTS, textual_hdrs = [ - "//upb/port:inc", + ":port_inc", ], visibility = ["//visibility:public"], ) -cc_library( - name = "generated_reflection_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", - hdrs = [ - "reflection/def.h", - "reflection/internal/def_pool.h", - ], - copts = UPB_DEFAULT_COPTS, - textual_hdrs = [ - "//upb/port:inc", - ], - visibility = ["//visibility:public"], - deps = [ - ":mem", - ":mini_descriptor", - ":reflection_internal", - ], -) +# Aliases ###################################################################### +# TODO: Remove these. -bootstrap_upb_proto_library( - name = "descriptor_upb_proto", - base_dir = "reflection/", - # TODO: Export 'net/proto2/proto/descriptor.upb.h' and remove "-layering_check". - features = ["-layering_check"], - google3_src_files = ["net/proto2/proto/descriptor.proto"], - google3_src_rules = ["//net/proto2/proto:descriptor_proto_source"], - oss_src_files = ["google/protobuf/descriptor.proto"], - oss_src_rules = ["//:descriptor_proto_srcs"], - oss_strip_prefix = "third_party/protobuf/github/bootstrap/src", - proto_lib_deps = ["//:descriptor_proto"], +alias( + name = "base", + actual = "//upb/base", visibility = ["//visibility:public"], ) -upb_proto_reflection_library( - name = "descriptor_upb_proto_reflection", +alias( + name = "base_internal", + actual = "//upb/base:internal", visibility = ["//visibility:public"], - deps = ["//:descriptor_proto"], ) -upb_minitable_proto_library( - name = "descriptor_upb_minitable_proto", - visibility = [ - "//upb:__subpackages__", - # begin:github_only - "//python:__subpackages__", - # end:github_only - ], - deps = ["//:descriptor_proto"], -) - -# TODO: Once we can delete the deprecated forwarding headers -# (= everything in upb/) we can move this build target down into reflection/ -bootstrap_cc_library( - name = "reflection", - hdrs = [ - "reflection/def.h", - "reflection/def.hpp", - "reflection/message.h", - "reflection/message.hpp", - ], - bootstrap_deps = [":reflection_internal"], - copts = UPB_DEFAULT_COPTS, +alias( + name = "collections", + actual = "//upb/collections", + deprecation = "use upb:message instead", visibility = ["//visibility:public"], - deps = [ - ":base", - ":mem", - ":message", - ":message_types", - ":message_value", - ":port", - ], ) -bootstrap_cc_library( - name = "reflection_internal", - srcs = [ - "reflection/def_pool.c", - "reflection/def_type.c", - "reflection/desc_state.c", - "reflection/enum_def.c", - "reflection/enum_reserved_range.c", - "reflection/enum_value_def.c", - "reflection/extension_range.c", - "reflection/field_def.c", - "reflection/file_def.c", - "reflection/internal/def_builder.c", - "reflection/internal/def_builder.h", - "reflection/internal/strdup2.c", - "reflection/internal/strdup2.h", - "reflection/message.c", - "reflection/message_def.c", - "reflection/message_reserved_range.c", - "reflection/method_def.c", - "reflection/oneof_def.c", - "reflection/service_def.c", - ], - hdrs = [ - "reflection/common.h", - "reflection/def.h", - "reflection/def.hpp", - "reflection/def_pool.h", - "reflection/def_type.h", - "reflection/enum_def.h", - "reflection/enum_reserved_range.h", - "reflection/enum_value_def.h", - "reflection/extension_range.h", - "reflection/field_def.h", - "reflection/file_def.h", - "reflection/internal/def_pool.h", - "reflection/internal/desc_state.h", - "reflection/internal/enum_def.h", - "reflection/internal/enum_reserved_range.h", - "reflection/internal/enum_value_def.h", - "reflection/internal/extension_range.h", - "reflection/internal/field_def.h", - "reflection/internal/file_def.h", - "reflection/internal/message_def.h", - "reflection/internal/message_reserved_range.h", - "reflection/internal/method_def.h", - "reflection/internal/oneof_def.h", - "reflection/internal/service_def.h", - "reflection/message.h", - "reflection/message.hpp", - "reflection/message_def.h", - "reflection/message_reserved_range.h", - "reflection/method_def.h", - "reflection/oneof_def.h", - "reflection/service_def.h", - ], - bootstrap_deps = [":descriptor_upb_proto"], - copts = UPB_DEFAULT_COPTS, +alias( + name = "descriptor_upb_proto", + actual = "//upb/reflection:descriptor_upb_proto", visibility = ["//visibility:public"], - deps = [ - ":base", - ":hash", - ":mem", - ":message", - ":message_accessors", - ":message_types", - ":message_value", - ":mini_descriptor", - ":mini_descriptor_internal", - ":mini_table", - ":port", - ], ) -# Aliases ###################################################################### -# TODO: Remove these. - alias( - name = "base", - actual = "//upb/base", + name = "descriptor_upb_minitable_proto", + actual = "//upb/reflection:descriptor_upb_minitable_proto", visibility = ["//visibility:public"], ) alias( - name = "base_internal", - actual = "//upb/base:internal", + name = "descriptor_upb_proto_reflection", + actual = "//upb/reflection:descriptor_upb_proto_reflection", visibility = ["//visibility:public"], ) alias( - name = "collections", - actual = "//upb/collections", - deprecation = "use upb:message instead", + name = "generated_reflection_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", + actual = "//upb/reflection:generated_reflection_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", visibility = ["//visibility:public"], ) @@ -438,6 +309,24 @@ alias( visibility = ["//visibility:public"], ) +alias( + name = "port_inc", + actual = "//upb/port:inc", + visibility = ["//visibility:public"], +) + +alias( + name = "reflection", + actual = "//upb/reflection", + visibility = ["//visibility:public"], +) + +alias( + name = "reflection_internal", + actual = "//upb/reflection:internal", + visibility = ["//visibility:public"], +) + alias( name = "text", actual = "//upb/text", @@ -474,28 +363,6 @@ alias( visibility = ["//visibility:public"], ) -# Tests ######################################################################## - -cc_test( - name = "def_builder_test", - srcs = [ - "reflection/common.h", - "reflection/def_type.h", - "reflection/internal/def_builder.h", - "reflection/internal/def_builder_test.cc", - ], - deps = [ - ":descriptor_upb_proto", - ":hash", - ":mem", - ":port", - ":reflection", - ":reflection_internal", - "@com_google_googletest//:gtest_main", - "@com_google_absl//absl/strings", - ], -) - # Internal C/C++ libraries ##################################################### cc_binary( diff --git a/upb/cmake/BUILD.bazel b/upb/cmake/BUILD.bazel index b2a5e5a7f8..3e40380e8b 100644 --- a/upb/cmake/BUILD.bazel +++ b/upb/cmake/BUILD.bazel @@ -96,6 +96,7 @@ sh_test( "//upb/mini_descriptor:source_files", "//upb/mini_table:source_files", "//upb/port:source_files", + "//upb/reflection:source_files", "//upb/text:source_files", "//upb/wire:source_files", "@utf8_range//:utf8_range_srcs", diff --git a/upb/conformance/BUILD b/upb/conformance/BUILD index c22ea41301..18cfc57c14 100644 --- a/upb/conformance/BUILD +++ b/upb/conformance/BUILD @@ -12,7 +12,7 @@ load( ) load( "//bazel:upb_proto_library.bzl", - "upb_proto_library", + "upb_c_proto_library", "upb_proto_reflection_library", ) @@ -28,7 +28,7 @@ config_setting( visibility = ["//visibility:public"], ) -upb_proto_library( +upb_c_proto_library( name = "conformance_upb_proto", testonly = 1, deps = ["//conformance:conformance_proto"], diff --git a/upb/json/BUILD b/upb/json/BUILD index 31840a4f29..b560854f50 100644 --- a/upb/json/BUILD +++ b/upb/json/BUILD @@ -3,7 +3,7 @@ load("//bazel:build_defs.bzl", "UPB_DEFAULT_COPTS") load( "//bazel:upb_proto_library.bzl", - "upb_proto_library", + "upb_c_proto_library", "upb_proto_reflection_library", ) @@ -64,7 +64,7 @@ proto_library( deps = ["//:struct_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "test_upb_proto", testonly = 1, deps = [":test_proto"], @@ -77,7 +77,7 @@ upb_proto_reflection_library( ) # TODO: This target arguably belongs in //google/protobuf/BUILD -upb_proto_library( +upb_c_proto_library( name = "struct_upb_proto", testonly = 1, deps = ["//:struct_proto"], diff --git a/upb/mem/arena.c b/upb/mem/arena.c index b9d3d9d8f9..43a546a32c 100644 --- a/upb/mem/arena.c +++ b/upb/mem/arena.c @@ -347,8 +347,10 @@ bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) { } } -void upb_Arena_IncRefFor(upb_Arena* arena, const void* owner) { +bool upb_Arena_IncRefFor(upb_Arena* arena, const void* owner) { _upb_ArenaRoot r; + if (upb_Arena_HasInitialBlock(arena)) return false; + retry: r = _upb_Arena_FindRoot(arena); if (upb_Atomic_CompareExchangeWeak( @@ -357,7 +359,7 @@ retry: _upb_Arena_RefCountFromTagged(r.tagged_count) + 1), memory_order_release, memory_order_acquire)) { // We incremented it successfully, so we are done. - return; + return true; } // We failed update due to parent switching on the arena. goto retry; diff --git a/upb/mem/arena.h b/upb/mem/arena.h index e4afceaa43..1cb9182f4b 100644 --- a/upb/mem/arena.h +++ b/upb/mem/arena.h @@ -47,7 +47,7 @@ UPB_API upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc); UPB_API void upb_Arena_Free(upb_Arena* a); UPB_API bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b); -void upb_Arena_IncRefFor(upb_Arena* arena, const void* owner); +bool upb_Arena_IncRefFor(upb_Arena* arena, const void* owner); void upb_Arena_DecRefFor(upb_Arena* arena, const void* owner); void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size); diff --git a/upb/mem/arena_test.cc b/upb/mem/arena_test.cc index 0b13e1a365..444bd0d901 100644 --- a/upb/mem/arena_test.cc +++ b/upb/mem/arena_test.cc @@ -213,6 +213,12 @@ TEST(ArenaTest, FuzzFuseIncRefCountRace) { for (auto& t : threads) t.join(); } +TEST(ArenaTest, IncRefCountShouldFailForInitialBlock) { + char buf1[1024]; + upb_Arena* arena = upb_Arena_Init(buf1, 1024, &upb_alloc_global); + EXPECT_FALSE(upb_Arena_IncRefFor(arena, nullptr)); +} + #endif } // namespace diff --git a/upb/message/BUILD b/upb/message/BUILD index 72a4500e67..22d4ea9319 100644 --- a/upb/message/BUILD +++ b/upb/message/BUILD @@ -12,7 +12,7 @@ load( ) load( "//bazel:upb_proto_library.bzl", - "upb_proto_library", + "upb_c_proto_library", "upb_proto_reflection_library", ) @@ -235,7 +235,7 @@ upb_minitable_proto_library( deps = [":message_test_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "message_test_upb_proto", testonly = 1, deps = [":message_test_proto"], @@ -377,7 +377,7 @@ upb_minitable_proto_library( deps = [":utf8_test_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "utf8_test_upb_proto", testonly = 1, deps = [":utf8_test_proto"], diff --git a/upb/mini_table/BUILD b/upb/mini_table/BUILD index ecf2bbbb1c..f4b2ffe845 100644 --- a/upb/mini_table/BUILD +++ b/upb/mini_table/BUILD @@ -51,7 +51,6 @@ cc_library( "//upb:base", "//upb:hash", "//upb:mem", - "//upb:message_types", "//upb:port", ], ) diff --git a/upb/reflection/BUILD b/upb/reflection/BUILD new file mode 100644 index 0000000000..bf0c0e4dbe --- /dev/null +++ b/upb/reflection/BUILD @@ -0,0 +1,190 @@ +# Copyright (c) 2009-2021, Google LLC +# All rights reserved. +# +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file or at +# https://developers.google.com/open-source/licenses/bsd + +load("//bazel:build_defs.bzl", "UPB_DEFAULT_COPTS") +load("//bazel:upb_minitable_proto_library.bzl", "upb_minitable_proto_library") +load("//bazel:upb_proto_library.bzl", "upb_proto_reflection_library") +load( + "//upb_generator:bootstrap_compiler.bzl", + "bootstrap_cc_library", + "bootstrap_upb_proto_library", +) + +bootstrap_upb_proto_library( + name = "descriptor_upb_proto", + base_dir = "", + # TODO: Export 'net/proto2/proto/descriptor.upb.h' and remove "-layering_check". + features = ["-layering_check"], + google3_src_files = ["net/proto2/proto/descriptor.proto"], + google3_src_rules = ["//net/proto2/proto:descriptor_proto_source"], + oss_src_files = ["google/protobuf/descriptor.proto"], + oss_src_rules = ["//:descriptor_proto_srcs"], + oss_strip_prefix = "third_party/protobuf/github/bootstrap/src", + proto_lib_deps = ["//:descriptor_proto"], + visibility = ["//visibility:public"], +) + +upb_proto_reflection_library( + name = "descriptor_upb_proto_reflection", + visibility = ["//visibility:public"], + deps = ["//:descriptor_proto"], +) + +upb_minitable_proto_library( + name = "descriptor_upb_minitable_proto", + visibility = ["//visibility:public"], + deps = ["//:descriptor_proto"], +) + +bootstrap_cc_library( + name = "reflection", + hdrs = [ + "def.h", + "def.hpp", + "message.h", + "message.hpp", + ], + bootstrap_deps = [":internal"], + copts = UPB_DEFAULT_COPTS, + visibility = ["//visibility:public"], + deps = [ + "//upb:base", + "//upb:mem", + "//upb:message", + "//upb:message_value", + "//upb:port", + ], +) + +bootstrap_cc_library( + name = "internal", + srcs = [ + "def_pool.c", + "def_type.c", + "desc_state.c", + "enum_def.c", + "enum_reserved_range.c", + "enum_value_def.c", + "extension_range.c", + "field_def.c", + "file_def.c", + "internal/def_builder.c", + "internal/def_builder.h", + "internal/strdup2.c", + "internal/strdup2.h", + "message.c", + "message_def.c", + "message_reserved_range.c", + "method_def.c", + "oneof_def.c", + "service_def.c", + ], + hdrs = [ + "common.h", + "def.h", + "def.hpp", + "def_pool.h", + "def_type.h", + "enum_def.h", + "enum_reserved_range.h", + "enum_value_def.h", + "extension_range.h", + "field_def.h", + "file_def.h", + "internal/def_pool.h", + "internal/desc_state.h", + "internal/enum_def.h", + "internal/enum_reserved_range.h", + "internal/enum_value_def.h", + "internal/extension_range.h", + "internal/field_def.h", + "internal/file_def.h", + "internal/message_def.h", + "internal/message_reserved_range.h", + "internal/method_def.h", + "internal/oneof_def.h", + "internal/service_def.h", + "message.h", + "message.hpp", + "message_def.h", + "message_reserved_range.h", + "method_def.h", + "oneof_def.h", + "service_def.h", + ], + bootstrap_deps = [":descriptor_upb_proto"], + copts = UPB_DEFAULT_COPTS, + visibility = ["//visibility:public"], + deps = [ + "//upb:base", + "//upb:hash", + "//upb:mem", + "//upb:message", + "//upb:message_accessors", + "//upb:message_value", + "//upb:mini_descriptor", + "//upb:mini_descriptor_internal", + "//upb:mini_table", + "//upb:port", + ], +) + +cc_library( + name = "generated_reflection_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", + hdrs = [ + "def.h", + "internal/def_pool.h", + ], + copts = UPB_DEFAULT_COPTS, + textual_hdrs = [ + "//upb:port_inc", + ], + visibility = ["//visibility:public"], + deps = [ + "//upb:mem", + "//upb:mini_descriptor", + "//upb:reflection_internal", + ], +) + +cc_test( + name = "def_builder_test", + srcs = [ + "common.h", + "def_type.h", + "internal/def_builder.h", + "internal/def_builder_test.cc", + ], + deps = [ + ":descriptor_upb_proto", + "@com_google_googletest//:gtest_main", + "//upb:hash", + "//upb:mem", + "//upb:port", + "//upb:reflection", + "//upb:reflection_internal", + "@com_google_absl//absl/strings", + ], +) + +# begin:github_only +filegroup( + name = "source_files", + srcs = glob( + [ + "**/*.c", + "**/*.h", + "**/*.hpp", + ], + exclude = ["stage0/**"], + ), + visibility = [ + "//upb/cmake:__pkg__", + "//python/dist:__pkg__", + ] +) +# end:github_only diff --git a/upb/reflection/message.h b/upb/reflection/message.h index 9e57c1a16e..54af6f15af 100644 --- a/upb/reflection/message.h +++ b/upb/reflection/message.h @@ -12,7 +12,7 @@ #include "upb/mem/arena.h" #include "upb/message/map.h" -#include "upb/message/types.h" +#include "upb/message/message.h" #include "upb/message/value.h" // IWYU pragma: export #include "upb/reflection/common.h" diff --git a/upb/test/BUILD b/upb/test/BUILD index b147e06c08..6ae451d029 100644 --- a/upb/test/BUILD +++ b/upb/test/BUILD @@ -15,7 +15,7 @@ load( ) load( "//bazel:upb_proto_library.bzl", - "upb_proto_library", + "upb_c_proto_library", "upb_proto_reflection_library", ) @@ -52,7 +52,7 @@ proto_library( deps = ["//:descriptor_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "proto3_test_upb_proto", testonly = 1, deps = [":proto3_test_proto"], @@ -77,7 +77,7 @@ upb_minitable_proto_library( deps = [":test_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "test_upb_proto", testonly = 1, visibility = ["//upb:__subpackages__"], @@ -90,7 +90,7 @@ proto_library( deps = ["//:timestamp_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "test_cpp_upb_proto", deps = ["test_cpp_proto"], ) @@ -114,21 +114,21 @@ upb_minitable_proto_library( deps = ["//src/google/protobuf:test_messages_proto3_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "test_messages_proto2_upb_proto", testonly = 1, visibility = ["//upb:__subpackages__"], deps = ["//src/google/protobuf:test_messages_proto2_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "test_messages_proto3_upb_proto", testonly = 1, visibility = ["//upb:__subpackages__"], deps = ["//src/google/protobuf:test_messages_proto3_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "timestamp_upb_proto", deps = ["//:timestamp_proto"], ) @@ -252,7 +252,7 @@ upb_minitable_proto_library( deps = [":test_import_empty_srcs_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "test_import_empty_srcs_upb_proto", testonly = 1, deps = [":test_import_empty_srcs_proto"], diff --git a/upb/test/test_cpp.cc b/upb/test/test_cpp.cc index bd917c1d9b..a2d1c4c456 100644 --- a/upb/test/test_cpp.cc +++ b/upb/test/test_cpp.cc @@ -57,7 +57,7 @@ TEST(Cpp, Default) { upb::Arena arena; upb::MessageDefPtr md(upb_test_TestMessage_getmsgdef(defpool.ptr())); upb_test_TestMessage* msg = upb_test_TestMessage_new(arena.ptr()); - size_t size = upb_JsonEncode(msg, md.ptr(), NULL, 0, NULL, 0, NULL); + size_t size = upb_JsonEncode(msg, md.ptr(), nullptr, 0, nullptr, 0, nullptr); EXPECT_EQ(2, size); // "{}" } @@ -95,10 +95,10 @@ TEST(Cpp, TimestampEncoder) { google_protobuf_Timestamp_set_seconds(timestamp_upb, timestamp); char json[128]; - size_t size = upb_JsonEncode(timestamp_upb, md.ptr(), NULL, 0, json, - sizeof(json), NULL); + size_t size = upb_JsonEncode(timestamp_upb, md.ptr(), nullptr, 0, json, + sizeof(json), nullptr); bool result = upb_JsonDecode(json, size, timestamp_upb_decoded, md.ptr(), - NULL, 0, arena.ptr(), NULL); + nullptr, 0, arena.ptr(), nullptr); const int64_t timestamp_decoded = google_protobuf_Timestamp_seconds(timestamp_upb_decoded); diff --git a/upb/test/test_generated_code.cc b/upb/test/test_generated_code.cc index 2a2d723654..4169d5d865 100644 --- a/upb/test/test_generated_code.cc +++ b/upb/test/test_generated_code.cc @@ -706,6 +706,21 @@ TEST(GeneratedCode, Int32Map) { check_int32_map_empty(msg); + EXPECT_EQ( + _protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_upb_map( + msg), + nullptr); + + upb_Map* mut_map = + _protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_mutable_upb_map( + msg, arena); + EXPECT_NE(mut_map, nullptr); + + const upb_Map* const_map = + _protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_upb_map( + msg); + EXPECT_EQ(mut_map, const_map); + /* Set map[test_int32] = test_int32_2 */ protobuf_test_messages_proto3_TestAllTypesProto3_map_int32_int32_set( msg, test_int32, test_int32_2, arena); diff --git a/upb/util/BUILD b/upb/util/BUILD index 1abbaf070f..f354be10d8 100644 --- a/upb/util/BUILD +++ b/upb/util/BUILD @@ -1,6 +1,6 @@ load( "//bazel:upb_proto_library.bzl", - "upb_proto_library", + "upb_c_proto_library", "upb_proto_reflection_library", ) @@ -33,7 +33,7 @@ proto_library( ], ) -upb_proto_library( +upb_c_proto_library( name = "def_to_proto_test_upb_proto", deps = ["def_to_proto_test_proto"], ) @@ -99,7 +99,6 @@ cc_library( deps = [ "//upb:base", "//upb:message", - "//upb:message_types", "//upb:port", "//upb:reflection", ], @@ -110,7 +109,7 @@ proto_library( srcs = ["required_fields_test.proto"], ) -upb_proto_library( +upb_c_proto_library( name = "required_fields_test_upb_proto", deps = ["required_fields_test_proto"], ) diff --git a/upb/util/required_fields.c b/upb/util/required_fields.c index 4e66cdd9e6..c6616ecdd3 100644 --- a/upb/util/required_fields.c +++ b/upb/util/required_fields.c @@ -19,7 +19,7 @@ #include "upb/base/descriptor_constants.h" #include "upb/message/array.h" #include "upb/message/map.h" -#include "upb/message/types.h" +#include "upb/message/message.h" #include "upb/port/vsnprintf_compat.h" #include "upb/reflection/def.h" #include "upb/reflection/message.h" diff --git a/upb_generator/BUILD b/upb_generator/BUILD index bf0a1b9143..723d490402 100644 --- a/upb_generator/BUILD +++ b/upb_generator/BUILD @@ -16,7 +16,7 @@ load( ) load( "//bazel:upb_proto_library.bzl", - "upb_proto_library", + "upb_c_proto_library", "upb_proto_reflection_library", ) load( @@ -39,7 +39,7 @@ proto_library( deps = ["//:compiler_plugin_proto"], ) -upb_proto_library( +upb_c_proto_library( name = "code_generator_request_upb_proto", visibility = ["//upb:friends"], deps = [":code_generator_request"], @@ -79,7 +79,7 @@ bootstrap_upb_proto_library( oss_strip_prefix = "third_party/protobuf/github/bootstrap/src", proto_lib_deps = ["//:compiler_plugin_proto"], visibility = ["//upb:friends"], - deps = ["//upb:descriptor_upb_proto"], + deps = ["//upb/reflection:descriptor_upb_proto"], ) upb_proto_reflection_library( @@ -97,7 +97,7 @@ bootstrap_cc_library( "common.h", ], bootstrap_deps = [ - "//upb:reflection", + "//upb/reflection:reflection", ], copts = UPB_DEFAULT_CPPOPTS, visibility = ["//protos_generator:__pkg__"], @@ -119,8 +119,8 @@ bootstrap_cc_library( ], bootstrap_deps = [ ":common", - "//upb:reflection", - "//upb:descriptor_upb_proto", + "//upb/reflection:reflection", + "//upb/reflection:descriptor_upb_proto", ], copts = UPB_DEFAULT_CPPOPTS, visibility = ["//visibility:public"], @@ -154,8 +154,8 @@ bootstrap_cc_library( ], bootstrap_deps = [ ":plugin_upb_proto", - "//upb:descriptor_upb_proto", - "//upb:reflection", + "//upb/reflection:descriptor_upb_proto", + "//upb/reflection:reflection", ], copts = UPB_DEFAULT_CPPOPTS, visibility = ["//protos_generator:__pkg__"], @@ -177,7 +177,7 @@ bootstrap_cc_library( "names.h", ], bootstrap_deps = [ - "//upb:reflection", + "//upb/reflection:reflection", ], copts = UPB_DEFAULT_CPPOPTS, visibility = ["//protos_generator:__pkg__"], @@ -244,8 +244,8 @@ bootstrap_cc_binary( ":names", ":plugin", ":plugin_upb_proto", - "//upb:descriptor_upb_proto", - "//upb:reflection", + "//upb/reflection:descriptor_upb_proto", + "//upb/reflection:reflection", ], copts = UPB_DEFAULT_CPPOPTS, visibility = ["//visibility:public"], @@ -283,8 +283,8 @@ bootstrap_cc_binary( ":names", ":plugin", ":plugin_upb_proto", - "//upb:descriptor_upb_proto", - "//upb:reflection", + "//upb/reflection:descriptor_upb_proto", + "//upb/reflection:reflection", ], copts = UPB_DEFAULT_CPPOPTS, visibility = ["//visibility:public"], diff --git a/upb_generator/names.cc b/upb_generator/names.cc index 847c8f1b18..31f8c6457f 100644 --- a/upb_generator/names.cc +++ b/upb_generator/names.cc @@ -55,6 +55,10 @@ ABSL_CONST_INIT const absl::string_view kRepeatedFieldArrayGetterPostfix = ABSL_CONST_INIT const absl::string_view kRepeatedFieldMutableArrayGetterPostfix = "mutable_upb_array"; +ABSL_CONST_INIT const absl::string_view kMapGetterPostfix = "upb_map"; +ABSL_CONST_INIT const absl::string_view kMutableMapGetterPostfix = + "mutable_upb_map"; + // List of generated accessor prefixes to check against. // Example: // optional repeated string phase = 236; diff --git a/upb_generator/names.h b/upb_generator/names.h index 7eef159451..1694dde454 100644 --- a/upb_generator/names.h +++ b/upb_generator/names.h @@ -69,6 +69,10 @@ ABSL_CONST_INIT extern const absl::string_view kRepeatedFieldArrayGetterPostfix; ABSL_CONST_INIT extern const absl::string_view kRepeatedFieldMutableArrayGetterPostfix; +// Private getter name postfix for map fields. +ABSL_CONST_INIT extern const absl::string_view kMapGetterPostfix; +ABSL_CONST_INIT extern const absl::string_view kMutableMapGetterPostfix; + } // namespace generator } // namespace upb diff --git a/upb_generator/protoc-gen-upb.cc b/upb_generator/protoc-gen-upb.cc index eb839790c2..dac5bd6383 100644 --- a/upb_generator/protoc-gen-upb.cc +++ b/upb_generator/protoc-gen-upb.cc @@ -487,6 +487,27 @@ void GenerateMapGetters(upb::FieldDefPtr field, const DefPoolPair& pools, )cc", CTypeConst(field), msg_name, resolved_name, FieldInitializer(pools, field, options)); + // Generate private getter returning a upb_Map or NULL for immutable and + // a upb_Map for mutable. + // + // Example: + // UPB_INLINE const upb_Map* _name_immutable_upb_map(Foo* msg) + // UPB_INLINE upb_Map* _name_mutable_upb_map(Foo* msg, upb_Arena* a) + output( + R"cc( + UPB_INLINE const upb_Map* _$0_$1_$2($0* msg) { + const upb_MiniTableField field = $4; + return upb_Message_GetMap(msg, &field); + } + UPB_INLINE upb_Map* _$0_$1_$3($0* msg, upb_Arena* a) { + const upb_MiniTableField field = $4; + return _upb_Message_GetOrCreateMutableMap(msg, &field, $5, $6, a); + } + )cc", + msg_name, resolved_name, kMapGetterPostfix, kMutableMapGetterPostfix, + FieldInitializer(pools, field, options), + MapKeySize(field, MapKeyCType(field)), + MapValueSize(field, MapValueCType(field))); } void GenerateMapEntryGetters(upb::FieldDefPtr field, absl::string_view msg_name, @@ -814,15 +835,6 @@ void GenerateMessageInHeader(upb::MessageDefPtr message, output("\n"); } -void ForwardDeclareMiniTableInit(upb::MessageDefPtr message, - const Options& options, Output& output) { - if (options.bootstrap) { - output("extern const upb_MiniTable* $0();\n", MessageInitName(message)); - } else { - output("extern const upb_MiniTable $0;\n", MessageInitName(message)); - } -} - std::vector SortedForwardMessages( const std::vector& this_file_messages, const std::vector& this_file_exts) { @@ -1137,17 +1149,17 @@ int main(int argc, char** argv) { upb::generator::Plugin plugin; upb::generator::Options options; if (!ParseOptions(&plugin, &options)) return 0; - plugin.GenerateFilesRaw([&](const UPB_DESC(FileDescriptorProto) * file_proto, - bool generate) { - upb::Status status; - upb::FileDefPtr file = pools.AddFile(file_proto, &status); - if (!file) { - absl::string_view name = upb::generator::ToStringView( - UPB_DESC(FileDescriptorProto_name)(file_proto)); - ABSL_LOG(FATAL) << "Couldn't add file " << name - << " to DefPool: " << status.error_message(); - } - if (generate) GenerateFile(pools, file, options, &plugin); - }); + plugin.GenerateFilesRaw( + [&](const UPB_DESC(FileDescriptorProto) * file_proto, bool generate) { + upb::Status status; + upb::FileDefPtr file = pools.AddFile(file_proto, &status); + if (!file) { + absl::string_view name = upb::generator::ToStringView( + UPB_DESC(FileDescriptorProto_name)(file_proto)); + ABSL_LOG(FATAL) << "Couldn't add file " << name + << " to DefPool: " << status.error_message(); + } + if (generate) GenerateFile(pools, file, options, &plugin); + }); return 0; } diff --git a/upb_generator/protoc-gen-upbdefs.cc b/upb_generator/protoc-gen-upbdefs.cc index 69682c4e78..58234150a2 100644 --- a/upb_generator/protoc-gen-upbdefs.cc +++ b/upb_generator/protoc-gen-upbdefs.cc @@ -70,17 +70,13 @@ void WriteDefHeader(upb::FileDefPtr file, Output& output) { "#define $0_UPBDEFS_H_\n\n" "#include \"upb/reflection/def.h\"\n" "#include \"upb/reflection/internal/def_pool.h\"\n" - "#include \"upb/port/def.inc\"\n" + "\n" + "#include \"upb/port/def.inc\" // Must be last.\n" "#ifdef __cplusplus\n" "extern \"C\" {\n" "#endif\n\n", ToPreproc(file.name())); - output("#include \"upb/reflection/def.h\"\n"); - output("\n"); - output("#include \"upb/port/def.inc\"\n"); - output("\n"); - output("extern _upb_DefPool_Init $0;\n", DefInitSymbol(file)); output("\n"); diff --git a/version.json b/version.json index ba0cf35f44..fb4e0df57b 100644 --- a/version.json +++ b/version.json @@ -1,17 +1,17 @@ { - "25.x": { - "protoc_version": "25.1-dev", + "main": { + "protoc_version": "26-dev", "lts": false, "date": "2023-11-01", "languages": { - "cpp": "4.25.1-dev", - "csharp": "3.25.1-dev", - "java": "3.25.1-dev", - "javascript": "3.25.1-dev", - "objectivec": "3.25.1-dev", - "php": "3.25.1-dev", - "python": "4.25.1-dev", - "ruby": "3.25.1-dev" + "cpp": "4.26-dev", + "csharp": "3.26-dev", + "java": "3.26-dev", + "javascript": "3.26-dev", + "objectivec": "3.26-dev", + "php": "3.26-dev", + "python": "4.26-dev", + "ruby": "3.26-dev" } } } \ No newline at end of file